mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-11-18 07:12:20 +00:00
5b3a82d621
- The ambiguous character detection is an important security feature to combat against sourcebase attacks (https://trojansource.codes/). - However there are a few problems with the feature as it stands today (i) it's apparantly an big performance hitter, it's twice as slow as syntax highlighting (ii) it contains false positives, because it's reporting valid problems but not valid within the context of a programming language (ambiguous charachters in code comments being a prime example) that can lead to security issues (iii) charachters from certain languages always being marked as ambiguous. It's a lot of effort to fix the aforementioned issues. - Therefore, make it configurable in which context the ambiguous character detection should be run, this avoids running detection in all contexts such as file views, but still enable it in commits and pull requests diffs where it matters the most. Ideally this also becomes an per-repository setting, but the code architecture doesn't allow for a clean implementation of that. - Adds unit test. - Adds integration tests to ensure that the contexts and instance-wide is respected (and that ambigious charachter detection actually work in different places). - Ref: https://codeberg.org/forgejo/forgejo/pulls/2395#issuecomment-1575547 - Ref: https://codeberg.org/forgejo/forgejo/issues/564
131 lines
4.1 KiB
Go
131 lines
4.1 KiB
Go
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||
// SPDX-License-Identifier: MIT
|
||
|
||
package integration
|
||
|
||
import (
|
||
"net/http"
|
||
"net/url"
|
||
"strings"
|
||
"testing"
|
||
|
||
unit_model "code.gitea.io/gitea/models/unit"
|
||
"code.gitea.io/gitea/models/unittest"
|
||
user_model "code.gitea.io/gitea/models/user"
|
||
"code.gitea.io/gitea/modules/setting"
|
||
"code.gitea.io/gitea/modules/test"
|
||
files_service "code.gitea.io/gitea/services/repository/files"
|
||
"code.gitea.io/gitea/tests"
|
||
|
||
"github.com/stretchr/testify/assert"
|
||
)
|
||
|
||
func TestRenderFileSVGIsInImgTag(t *testing.T) {
|
||
defer tests.PrepareTestEnv(t)()
|
||
|
||
session := loginUser(t, "user2")
|
||
|
||
req := NewRequest(t, "GET", "/user2/repo2/src/branch/master/line.svg")
|
||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||
|
||
doc := NewHTMLParser(t, resp.Body)
|
||
src, exists := doc.doc.Find(".file-view img").Attr("src")
|
||
assert.True(t, exists, "The SVG image should be in an <img> tag so that scripts in the SVG are not run")
|
||
assert.Equal(t, "/user2/repo2/raw/branch/master/line.svg", src)
|
||
}
|
||
|
||
func TestAmbiguousCharacterDetection(t *testing.T) {
|
||
onGiteaRun(t, func(t *testing.T, u *url.URL) {
|
||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||
session := loginUser(t, user2.Name)
|
||
|
||
// Prepare the environments. File view, commit view (diff), wiki page.
|
||
repo, commitID, f := CreateDeclarativeRepo(t, user2, "",
|
||
[]unit_model.Type{unit_model.TypeCode, unit_model.TypeWiki}, nil,
|
||
[]*files_service.ChangeRepoFile{
|
||
{
|
||
Operation: "create",
|
||
TreePath: "test.sh",
|
||
ContentReader: strings.NewReader("Hello there!\nline western"),
|
||
},
|
||
},
|
||
)
|
||
defer f()
|
||
|
||
req := NewRequestWithValues(t, "POST", repo.Link()+"/wiki?action=new", map[string]string{
|
||
"_csrf": GetCSRF(t, session, repo.Link()+"/wiki?action=new"),
|
||
"title": "Normal",
|
||
"content": "Hello – Hello",
|
||
})
|
||
session.MakeRequest(t, req, http.StatusSeeOther)
|
||
|
||
assertCase := func(t *testing.T, fileContext, commitContext, wikiContext bool) {
|
||
t.Helper()
|
||
|
||
t.Run("File context", func(t *testing.T) {
|
||
defer tests.PrintCurrentTest(t)()
|
||
|
||
req := NewRequest(t, "GET", repo.Link()+"/src/branch/main/test.sh")
|
||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||
|
||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||
htmlDoc.AssertElement(t, ".unicode-escape-prompt", fileContext)
|
||
})
|
||
t.Run("Commit context", func(t *testing.T) {
|
||
defer tests.PrintCurrentTest(t)()
|
||
|
||
req := NewRequest(t, "GET", repo.Link()+"/commit/"+commitID)
|
||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||
|
||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||
htmlDoc.AssertElement(t, ".lines-escape .toggle-escape-button", commitContext)
|
||
})
|
||
t.Run("Wiki context", func(t *testing.T) {
|
||
defer tests.PrintCurrentTest(t)()
|
||
|
||
req := NewRequest(t, "GET", repo.Link()+"/wiki/Normal")
|
||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||
|
||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||
htmlDoc.AssertElement(t, ".unicode-escape-prompt", wikiContext)
|
||
})
|
||
}
|
||
|
||
t.Run("Enabled all context", func(t *testing.T) {
|
||
defer test.MockVariableValue(&setting.UI.SkipEscapeContexts, []string{})()
|
||
|
||
assertCase(t, true, true, true)
|
||
})
|
||
|
||
t.Run("Enabled file context", func(t *testing.T) {
|
||
defer test.MockVariableValue(&setting.UI.SkipEscapeContexts, []string{"diff", "wiki"})()
|
||
|
||
assertCase(t, true, false, false)
|
||
})
|
||
|
||
t.Run("Enabled commit context", func(t *testing.T) {
|
||
defer test.MockVariableValue(&setting.UI.SkipEscapeContexts, []string{"file-view", "wiki"})()
|
||
|
||
assertCase(t, false, true, false)
|
||
})
|
||
|
||
t.Run("Enabled wiki context", func(t *testing.T) {
|
||
defer test.MockVariableValue(&setting.UI.SkipEscapeContexts, []string{"file-view", "diff"})()
|
||
|
||
assertCase(t, false, false, true)
|
||
})
|
||
|
||
t.Run("No context", func(t *testing.T) {
|
||
defer test.MockVariableValue(&setting.UI.SkipEscapeContexts, []string{"file-view", "wiki", "diff"})()
|
||
|
||
assertCase(t, false, false, false)
|
||
})
|
||
|
||
t.Run("Disabled detection", func(t *testing.T) {
|
||
defer test.MockVariableValue(&setting.UI.SkipEscapeContexts, []string{})()
|
||
defer test.MockVariableValue(&setting.UI.AmbiguousUnicodeDetection, false)()
|
||
|
||
assertCase(t, false, false, false)
|
||
})
|
||
})
|
||
}
|