44package integration
55
66import (
7+ "context"
8+ "fmt"
79 "net/http"
10+ "net/url"
11+ "os"
12+ "path/filepath"
13+ "strings"
814 "testing"
15+ "time"
916
1017 "code.gitea.io/gitea/models/unittest"
1118 user_model "code.gitea.io/gitea/models/user"
19+ "code.gitea.io/gitea/modules/git"
1220 "code.gitea.io/gitea/tests"
1321
22+ gogit "github.com/go-git/go-git/v5"
23+ "github.com/go-git/go-git/v5/plumbing/object"
1424 "github.com/stretchr/testify/assert"
1525)
1626
@@ -37,3 +47,78 @@ func TestXSSUserFullName(t *testing.T) {
3747 htmlDoc .doc .Find ("div.content" ).Find (".header.text.center" ).Text (),
3848 )
3949}
50+
51+ func TestXSSWikiLastCommitInfo (t * testing.T ) {
52+ onGiteaRun (t , func (t * testing.T , u * url.URL ) {
53+ // Prepare the environment.
54+ dstPath := t .TempDir ()
55+ r := fmt .Sprintf ("%suser2/repo1.wiki.git" , u .String ())
56+ u , err := url .Parse (r )
57+ assert .NoError (t , err )
58+ u .User = url .UserPassword ("user2" , userPassword )
59+ assert .NoError (t , git .CloneWithArgs (context .Background (), git .AllowLFSFiltersArgs (), u .String (), dstPath , git.CloneRepoOptions {}))
60+
61+ // Use go-git here, because using git wouldn't work, it has code to remove
62+ // `<`, `>` and `\n` in user names. Even though this is permitted and
63+ // wouldn't result in a error by a Git server.
64+ gitRepo , err := gogit .PlainOpen (dstPath )
65+ if err != nil {
66+ panic (err )
67+ }
68+
69+ w , err := gitRepo .Worktree ()
70+ if err != nil {
71+ panic (err )
72+ }
73+
74+ filename := filepath .Join (dstPath , "Home.md" )
75+ err = os .WriteFile (filename , []byte ("Oh, a XSS attack?" ), 0o644 )
76+ if ! assert .NoError (t , err ) {
77+ t .FailNow ()
78+ }
79+
80+ _ , err = w .Add ("Home.md" )
81+ if ! assert .NoError (t , err ) {
82+ t .FailNow ()
83+ }
84+
85+ _ , err = w .Commit ("Yay XSS" , & gogit.CommitOptions {
86+ Author : & object.Signature {
87+ Name : `Gusted <script class="evil">alert('Oh no!');</script>` ,
88+ 89+ When : time .Date (2024 , time .January , 31 , 0 , 0 , 0 , 0 , time .UTC ),
90+ },
91+ })
92+ if ! assert .NoError (t , err ) {
93+ t .FailNow ()
94+ }
95+
96+ // Push.
97+ _ , _ , err = git .NewCommand (git .DefaultContext , "push" ).AddArguments (git .ToTrustedCmdArgs ([]string {"origin" , "master" })... ).RunStdString (& git.RunOpts {Dir : dstPath })
98+ assert .NoError (t , err )
99+
100+ // Check on page view.
101+ t .Run ("Page view" , func (t * testing.T ) {
102+ defer tests .PrintCurrentTest (t )()
103+
104+ req := NewRequest (t , http .MethodGet , "/user2/repo1/wiki/Home" )
105+ resp := MakeRequest (t , req , http .StatusOK )
106+ htmlDoc := NewHTMLParser (t , resp .Body )
107+
108+ htmlDoc .AssertElement (t , "script.evil" , false )
109+ assert .EqualValues (t , `Gusted edited this page 0001-01-01 00:00:00 +00:00` , strings .TrimSpace (htmlDoc .Find (".ui.sub.header" ).Text ()))
110+ })
111+
112+ // Check on revisions page.
113+ t .Run ("Revision page" , func (t * testing.T ) {
114+ defer tests .PrintCurrentTest (t )()
115+
116+ req := NewRequest (t , http .MethodGet , "/user2/repo1/wiki/Home?action=_revision" )
117+ resp := MakeRequest (t , req , http .StatusOK )
118+ htmlDoc := NewHTMLParser (t , resp .Body )
119+
120+ htmlDoc .AssertElement (t , "script.evil" , false )
121+ assert .EqualValues (t , `Gusted edited this page 0001-01-01 00:00:00 +00:00` , strings .TrimSpace (htmlDoc .Find (".ui.sub.header" ).Text ()))
122+ })
123+ })
124+ }
0 commit comments