[SECURITY] Test XSS in wiki last commit information
On the wiki and revisions page, information is shown about the last
commit that modified that wiki page. This includes the time it was last
edited and by whom. Verify it is sanitized.
(cherry picked from commit 565e331238
)
This commit is contained in:
parent
d24c37e132
commit
92dae3a387
1 changed files with 75 additions and 0 deletions
|
@ -4,14 +4,24 @@
|
||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/tests"
|
"code.gitea.io/gitea/tests"
|
||||||
|
|
||||||
|
gogit "github.com/go-git/go-git/v5"
|
||||||
|
"github.com/go-git/go-git/v5/plumbing/object"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestXSSUserFullName(t *testing.T) {
|
func TestXSSUserFullName(t *testing.T) {
|
||||||
|
@ -37,3 +47,68 @@ func TestXSSUserFullName(t *testing.T) {
|
||||||
htmlDoc.doc.Find("div.content").Find(".header.text.center").Text(),
|
htmlDoc.doc.Find("div.content").Find(".header.text.center").Text(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestXSSWikiLastCommitInfo(t *testing.T) {
|
||||||
|
onGiteaRun(t, func(t *testing.T, u *url.URL) {
|
||||||
|
// Prepare the environment.
|
||||||
|
dstPath := t.TempDir()
|
||||||
|
r := fmt.Sprintf("%suser2/repo1.wiki.git", u.String())
|
||||||
|
u, err := url.Parse(r)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
u.User = url.UserPassword("user2", userPassword)
|
||||||
|
assert.NoError(t, git.CloneWithArgs(context.Background(), git.AllowLFSFiltersArgs(), u.String(), dstPath, git.CloneRepoOptions{}))
|
||||||
|
|
||||||
|
// Use go-git here, because using git wouldn't work, it has code to remove
|
||||||
|
// `<`, `>` and `\n` in user names. Even though this is permitted and
|
||||||
|
// wouldn't result in a error by a Git server.
|
||||||
|
gitRepo, err := gogit.PlainOpen(dstPath)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
w, err := gitRepo.Worktree()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
filename := filepath.Join(dstPath, "Home.md")
|
||||||
|
err = os.WriteFile(filename, []byte("Oh, a XSS attack?"), 0o644)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
_, err = w.Add("Home.md")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
_, err = w.Commit("Yay XSS", &gogit.CommitOptions{
|
||||||
|
Author: &object.Signature{
|
||||||
|
Name: `Gusted<script class="evil">alert('Oh no!');</script>`,
|
||||||
|
Email: "valid@example.org",
|
||||||
|
When: time.Date(2024, time.January, 31, 0, 0, 0, 0, time.UTC),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Push.
|
||||||
|
_, _, err = git.NewCommand(git.DefaultContext, "push").AddArguments(git.ToTrustedCmdArgs([]string{"origin", "master"})...).RunStdString(&git.RunOpts{Dir: dstPath})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Check on page view.
|
||||||
|
t.Run("Page view", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
|
req := NewRequest(t, http.MethodGet, "/user2/repo1/wiki/Home")
|
||||||
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||||
|
|
||||||
|
htmlDoc.AssertElement(t, "script.evil", false)
|
||||||
|
assert.Contains(t, htmlDoc.Find(".ui.sub.header").Text(), `Gusted<script class="evil">alert('Oh no!');</script> edited this page 2024-01-31`)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Check on revisions page.
|
||||||
|
t.Run("Revision page", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
|
req := NewRequest(t, http.MethodGet, "/user2/repo1/wiki/Home?action=_revision")
|
||||||
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||||
|
|
||||||
|
htmlDoc.AssertElement(t, "script.evil", false)
|
||||||
|
assert.Contains(t, htmlDoc.Find(".ui.sub.header").Text(), `Gusted<script class="evil">alert('Oh no!');</script> edited this page 2024-01-31`)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue