summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Provaznik <jprovaznik@gitlab.com>2018-10-24 09:01:46 +0000
committerThiago Presa <tpresa@gitlab.com>2018-10-24 21:06:13 -0300
commit5342df04045e1c8a98fdb9fe8203a816bf240ac8 (patch)
treea4eada079ad61e0aca1c10a28f66a26e76beb5d5
parent82c12bd8bf9e0ea9e8df3bbcad91c27fccc709e8 (diff)
downloadgitlab-ce-5342df04045e1c8a98fdb9fe8203a816bf240ac8.tar.gz
Merge branch 'security-11-4-2717-fix-issue-title-xss' into 'security-11-4'
[11.4] Escape issue title while template rendering to prevent XSS See merge request gitlab/gitlabhq!2571
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js11
-rw-r--r--changelogs/unreleased/security-11-4-2717-fix-issue-title-xss.yml5
-rw-r--r--spec/features/issues/gfm_autocomplete_spec.rb15
3 files changed, 26 insertions, 5 deletions
diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js
index 95636a9ccdd..7dd0efd622d 100644
--- a/app/assets/javascripts/gfm_auto_complete.js
+++ b/app/assets/javascripts/gfm_auto_complete.js
@@ -201,7 +201,7 @@ class GfmAutoComplete {
displayTpl(value) {
let tmpl = GfmAutoComplete.Loading.template;
if (value.title != null) {
- tmpl = GfmAutoComplete.Issues.template;
+ tmpl = GfmAutoComplete.Issues.templateFunction(value.id, value.title);
}
return tmpl;
},
@@ -267,7 +267,7 @@ class GfmAutoComplete {
displayTpl(value) {
let tmpl = GfmAutoComplete.Loading.template;
if (value.title != null) {
- tmpl = GfmAutoComplete.Issues.template;
+ tmpl = GfmAutoComplete.Issues.templateFunction(value.id, value.title);
}
return tmpl;
},
@@ -370,7 +370,7 @@ class GfmAutoComplete {
displayTpl(value) {
let tmpl = GfmAutoComplete.Loading.template;
if (value.title != null) {
- tmpl = GfmAutoComplete.Issues.template;
+ tmpl = GfmAutoComplete.Issues.templateFunction(value.id, value.title);
}
return tmpl;
},
@@ -557,8 +557,9 @@ GfmAutoComplete.Labels = {
};
// Issues, MergeRequests and Snippets
GfmAutoComplete.Issues = {
- // eslint-disable-next-line no-template-curly-in-string
- template: '<li><small>${id}</small> ${title}</li>',
+ templateFunction(id, title) {
+ return `<li><small>${id}</small> ${_.escape(title)}</li>`;
+ },
};
// Milestones
GfmAutoComplete.Milestones = {
diff --git a/changelogs/unreleased/security-11-4-2717-fix-issue-title-xss.yml b/changelogs/unreleased/security-11-4-2717-fix-issue-title-xss.yml
new file mode 100644
index 00000000000..12dfa48c6aa
--- /dev/null
+++ b/changelogs/unreleased/security-11-4-2717-fix-issue-title-xss.yml
@@ -0,0 +1,5 @@
+---
+title: Escape entity title while autocomplete template rendering to prevent XSS
+merge_request: 2571
+author:
+type: security
diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb
index 08bf9bc7243..593dc6b6690 100644
--- a/spec/features/issues/gfm_autocomplete_spec.rb
+++ b/spec/features/issues/gfm_autocomplete_spec.rb
@@ -35,6 +35,21 @@ describe 'GFM autocomplete', :js do
expect(page).to have_selector('.atwho-container')
end
+ it 'opens autocomplete menu when field starts with text with item escaping HTML characters' do
+ alert_title = 'This will execute alert<img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;'
+ create(:issue, project: project, title: alert_title)
+
+ page.within '.timeline-content-form' do
+ find('#note-body').native.send_keys('#')
+ end
+
+ expect(page).to have_selector('.atwho-container')
+
+ page.within '.atwho-container #at-view-issues' do
+ expect(page.all('li').first.text).to include(alert_title)
+ end
+ end
+
it 'doesnt open autocomplete menu character is prefixed with text' do
page.within '.timeline-content-form' do
find('#note-body').native.send_keys('testing')