From 76b3f4cd6ad1a692199eec90db7c8b7985708d9d Mon Sep 17 00:00:00 2001 From: Robert Wolff Date: Fri, 27 Jun 2025 13:27:06 +0200 Subject: [PATCH] test: prevent XSS for label rendering --- models/fixtures/label.yml | 24 ++++++++++++++++++++++++ modules/templates/util_render_test.go | 27 +++++++++++++++++++++++---- services/convert/issue_test.go | 9 +++++---- 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/models/fixtures/label.yml b/models/fixtures/label.yml index acfac74968..84c2a7f418 100644 --- a/models/fixtures/label.yml +++ b/models/fixtures/label.yml @@ -3,6 +3,7 @@ repo_id: 1 org_id: 0 name: label1 + description: 'First label' color: '#abcdef' exclusive: false num_issues: 2 @@ -107,3 +108,26 @@ num_issues: 0 num_closed_issues: 0 archived_unix: 0 + +- + id: 11 + repo_id: 3 + org_id: 0 + name: " /'?&" + description: "Malicious label ' " + color: '#000000' + exclusive: true + num_issues: 0 + num_closed_issues: 0 + archived_unix: 0 + +- + id: 12 + repo_id: 3 + org_id: 0 + name: 'archived label<>' + color: '#000000' + exclusive: false + num_issues: 0 + num_closed_issues: 0 + archived_unix: 2991092130 diff --git a/modules/templates/util_render_test.go b/modules/templates/util_render_test.go index 00543a1b33..5974c34073 100644 --- a/modules/templates/util_render_test.go +++ b/modules/templates/util_render_test.go @@ -218,11 +218,30 @@ func TestRenderLabels(t *testing.T) { tr := &translation.MockLocale{} label := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1}) + labelScoped := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 7}) + labelMalicious := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 11}) + labelArchived := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 12}) - assert.Contains(t, RenderLabels(db.DefaultContext, tr, []*issues_model.Label{label}, "user2/repo1", false), - "user2/repo1/issues?labels=1") - assert.Contains(t, RenderLabels(db.DefaultContext, tr, []*issues_model.Label{label}, "user2/repo1", true), - "user2/repo1/pulls?labels=1") + rendered := RenderLabels(db.DefaultContext, tr, []*issues_model.Label{label}, "user2/repo1", false) + assert.Contains(t, rendered, "user2/repo1/issues?labels=1") + assert.Contains(t, rendered, ">label1<") + assert.Contains(t, rendered, "title='First label'") + rendered = RenderLabels(db.DefaultContext, tr, []*issues_model.Label{label}, "user2/repo1", true) + assert.Contains(t, rendered, "user2/repo1/pulls?labels=1") + assert.Contains(t, rendered, ">label1<") + rendered = RenderLabels(db.DefaultContext, tr, []*issues_model.Label{labelScoped}, "user2/repo1", false) + assert.Contains(t, rendered, "user2/repo1/issues?labels=7") + assert.Contains(t, rendered, ">scope<") + assert.Contains(t, rendered, ">label1<") + rendered = RenderLabels(db.DefaultContext, tr, []*issues_model.Label{labelMalicious}, "user2/repo1", false) + assert.Contains(t, rendered, "user2/repo1/issues?labels=11") + assert.Contains(t, rendered, "> <script>malicious</script> <") + assert.Contains(t, rendered, ">'?&<") + assert.Contains(t, rendered, "title='Malicious label ' <script>malicious</script>'") + rendered = RenderLabels(db.DefaultContext, tr, []*issues_model.Label{labelArchived}, "user2/repo1", false) + assert.Contains(t, rendered, "user2/repo1/issues?labels=12") + assert.Contains(t, rendered, ">archived label<><") + assert.Contains(t, rendered, "title='repo.issues.archived_label_description'") } func TestRenderUser(t *testing.T) { diff --git a/services/convert/issue_test.go b/services/convert/issue_test.go index 97bacfb229..ea8ad9b7ef 100644 --- a/services/convert/issue_test.go +++ b/services/convert/issue_test.go @@ -24,10 +24,11 @@ func TestLabel_ToLabel(t *testing.T) { label := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: label.RepoID}) assert.Equal(t, &api.Label{ - ID: label.ID, - Name: label.Name, - Color: "abcdef", - URL: fmt.Sprintf("%sapi/v1/repos/user2/repo1/labels/%d", setting.AppURL, label.ID), + ID: label.ID, + Name: label.Name, + Color: "abcdef", + Description: label.Description, + URL: fmt.Sprintf("%sapi/v1/repos/user2/repo1/labels/%d", setting.AppURL, label.ID), }, ToLabel(label, repo, nil)) }