code.gitea.io/gitea@v1.21.7/tests/integration/xss_test.go (about) 1 // Copyright 2017 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package integration 5 6 import ( 7 "context" 8 "html" 9 "net/http" 10 "net/url" 11 "os" 12 "path/filepath" 13 "strings" 14 "testing" 15 "time" 16 17 "code.gitea.io/gitea/models/unittest" 18 user_model "code.gitea.io/gitea/models/user" 19 "code.gitea.io/gitea/modules/git" 20 "code.gitea.io/gitea/tests" 21 22 gogit "github.com/go-git/go-git/v5" 23 "github.com/go-git/go-git/v5/plumbing/object" 24 "github.com/stretchr/testify/assert" 25 ) 26 27 func TestXSSUserFullName(t *testing.T) { 28 defer tests.PrepareTestEnv(t)() 29 user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) 30 const fullName = `name & <script class="evil">alert('xss');</script>` 31 32 session := loginUser(t, user.Name) 33 req := NewRequestWithValues(t, "POST", "/user/settings", map[string]string{ 34 "_csrf": GetCSRF(t, session, "/user/settings"), 35 "name": user.Name, 36 "full_name": fullName, 37 "email": user.Email, 38 "language": "en-US", 39 }) 40 session.MakeRequest(t, req, http.StatusSeeOther) 41 42 req = NewRequestf(t, "GET", "/%s", user.Name) 43 resp := session.MakeRequest(t, req, http.StatusOK) 44 htmlDoc := NewHTMLParser(t, resp.Body) 45 assert.EqualValues(t, 0, htmlDoc.doc.Find("script.evil").Length()) 46 htmlCode, err := htmlDoc.doc.Find("div.content").Find(".header.text.center").Html() 47 assert.NoError(t, err) 48 assert.EqualValues(t, html.EscapeString(fullName), htmlCode) 49 } 50 51 func TestXSSWikiLastCommitInfo(t *testing.T) { 52 onGiteaRun(t, func(t *testing.T, u *url.URL) { 53 dstPath := t.TempDir() 54 cloneWikiURL, err := url.Parse(u.String() + "user2/repo1.wiki.git") 55 assert.NoError(t, err) 56 cloneWikiURL.User = url.UserPassword("user2", userPassword) 57 assert.NoError(t, git.CloneWithArgs(context.Background(), git.AllowLFSFiltersArgs(), cloneWikiURL.String(), dstPath, git.CloneRepoOptions{})) 58 59 // Use go-git here, because using git wouldn't work, it has code to remove 60 // `<`, `>` and `\n` in user names. Even though this is permitted and 61 // wouldn't result in a error by a Git server. 62 gitRepo, err := gogit.PlainOpen(dstPath) 63 if !assert.NoError(t, err) { 64 return 65 } 66 w, err := gitRepo.Worktree() 67 if !assert.NoError(t, err) { 68 return 69 } 70 71 filename := filepath.Join(dstPath, "Home.md") 72 err = os.WriteFile(filename, []byte("dummy content"), 0o644) 73 if !assert.NoError(t, err) { 74 return 75 } 76 77 _, err = w.Add("Home.md") 78 if !assert.NoError(t, err) { 79 return 80 } 81 82 _, err = w.Commit("dummy message", &gogit.CommitOptions{ 83 Author: &object.Signature{ 84 Name: `foo<script class="evil">alert('xss');</script>bar`, 85 Email: "valid@example.org", 86 When: time.Date(2001, time.January, 31, 0, 0, 0, 0, time.UTC), 87 }, 88 }) 89 if !assert.NoError(t, err) { 90 return 91 } 92 93 // Push. 94 _, _, err = git.NewCommand(git.DefaultContext, "push").AddArguments("origin", "master").RunStdString(&git.RunOpts{Dir: dstPath}) 95 assert.NoError(t, err) 96 97 // Check on page view. 98 t.Run("Page view", func(t *testing.T) { 99 defer tests.PrintCurrentTest(t)() 100 101 req := NewRequest(t, http.MethodGet, "/user2/repo1/wiki/Home") 102 resp := MakeRequest(t, req, http.StatusOK) 103 htmlDoc := NewHTMLParser(t, resp.Body) 104 105 htmlDoc.AssertElement(t, "script.evil", false) 106 htmlCode, err := htmlDoc.Find(".ui.sub.header").Html() 107 assert.NoError(t, err) 108 assert.EqualValues(t, `foo<script class="evil">alert('xss');</script>bar edited this page <relative-time class="time-since" prefix="" tense="past" datetime="2001-01-31T00:00:00Z" data-tooltip-content="" data-tooltip-interactive="true">2001-01-31 00:00:00 +00:00</relative-time>`, strings.TrimSpace(htmlCode)) 109 }) 110 111 // Check on revisions page. 112 t.Run("Revision page", func(t *testing.T) { 113 defer tests.PrintCurrentTest(t)() 114 115 req := NewRequest(t, http.MethodGet, "/user2/repo1/wiki/Home?action=_revision") 116 resp := MakeRequest(t, req, http.StatusOK) 117 htmlDoc := NewHTMLParser(t, resp.Body) 118 119 htmlDoc.AssertElement(t, "script.evil", false) 120 htmlCode, err := htmlDoc.Find(".ui.sub.header").Html() 121 assert.NoError(t, err) 122 assert.EqualValues(t, `foo<script class="evil">alert('xss');</script>bar edited this page <relative-time class="time-since" prefix="" tense="past" datetime="2001-01-31T00:00:00Z" data-tooltip-content="" data-tooltip-interactive="true">2001-01-31 00:00:00 +00:00</relative-time>`, strings.TrimSpace(htmlCode)) 123 }) 124 }) 125 }