4
4
package integration
5
5
6
6
import (
7
+ "context"
8
+ "fmt"
7
9
"net/http"
10
+ "net/url"
11
+ "os"
12
+ "path/filepath"
13
+ "strings"
8
14
"testing"
15
+ "time"
9
16
10
17
"code.gitea.io/gitea/models/unittest"
11
18
user_model "code.gitea.io/gitea/models/user"
19
+ "code.gitea.io/gitea/modules/git"
12
20
"code.gitea.io/gitea/tests"
13
21
22
+ gogit "github.com/go-git/go-git/v5"
23
+ "github.com/go-git/go-git/v5/plumbing/object"
14
24
"github.com/stretchr/testify/assert"
15
25
)
16
26
@@ -37,3 +47,78 @@ func TestXSSUserFullName(t *testing.T) {
37
47
htmlDoc .doc .Find ("div.content" ).Find (".header.text.center" ).Text (),
38
48
)
39
49
}
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