summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilipa Lacerda <filipa@gitlab.com>2017-05-25 14:32:14 +0100
committerFilipa Lacerda <filipa@gitlab.com>2017-05-25 14:32:14 +0100
commitdc2ac9937a378f4351ba34bb6fab93558f93d611 (patch)
treedd1b842005418cfe76db8c5a5f717680c3ad0cf3
parentc013d23d6320487cf293891f7c6b213cab816980 (diff)
downloadgitlab-ce-dc2ac9937a378f4351ba34bb6fab93558f93d611.tar.gz
Escapes html content before appending it to the DOM
-rw-r--r--app/assets/javascripts/notes.js4
-rw-r--r--changelogs/unreleased/32908-edit-comment.yml4
-rw-r--r--spec/javascripts/notes_spec.js39
3 files changed, 45 insertions, 2 deletions
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index b0b1cfd6c8a..702915c516f 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -1398,7 +1398,7 @@ const normalizeNewlines = function(str) {
const cachedNoteBodyText = $noteBodyText.html();
// Show updated comment content temporarily
- $noteBodyText.html(formContent);
+ $noteBodyText.html(_.escape(formContent));
$editingNote.removeClass('is-editing fade-in-full').addClass('being-posted fade-in-half');
$editingNote.find('.note-headline-meta a').html('<i class="fa fa-spinner fa-spin" aria-label="Comment is being updated" aria-hidden="true"></i>');
@@ -1411,7 +1411,7 @@ const normalizeNewlines = function(str) {
})
.fail(() => {
// Submission failed, revert back to original note
- $noteBodyText.html(cachedNoteBodyText);
+ $noteBodyText.html(_.escape(cachedNoteBodyText));
$editingNote.removeClass('being-posted fade-in');
$editingNote.find('.fa.fa-spinner').remove();
diff --git a/changelogs/unreleased/32908-edit-comment.yml b/changelogs/unreleased/32908-edit-comment.yml
new file mode 100644
index 00000000000..5237dceed11
--- /dev/null
+++ b/changelogs/unreleased/32908-edit-comment.yml
@@ -0,0 +1,4 @@
+---
+title: Escapes html content before appending it to the DOM
+merge_request:
+author:
diff --git a/spec/javascripts/notes_spec.js b/spec/javascripts/notes_spec.js
index 025f08ee332..ccd703b5b4b 100644
--- a/spec/javascripts/notes_spec.js
+++ b/spec/javascripts/notes_spec.js
@@ -443,6 +443,45 @@ import '~/notes';
});
});
+ describe('update comment with script tags', () => {
+ const sampleComment = '<script></script>';
+ const updatedComment = '<script></script>';
+ const note = {
+ id: 1234,
+ html: `<li class="note note-row-1234 timeline-entry" id="note_1234">
+ <div class="note-text">${sampleComment}</div>
+ </li>`,
+ note: sampleComment,
+ valid: true
+ };
+ let $form;
+ let $notesContainer;
+
+ beforeEach(() => {
+ this.notes = new Notes('', []);
+ window.gon.current_username = 'root';
+ window.gon.current_user_fullname = 'Administrator';
+ $form = $('form.js-main-target-form');
+ $notesContainer = $('ul.main-notes-list');
+ $form.find('textarea.js-note-text').html(sampleComment);
+ });
+
+ it('should not render a script tag', () => {
+ const deferred = $.Deferred();
+ spyOn($, 'ajax').and.returnValue(deferred.promise());
+ $('.js-comment-button').click();
+
+ deferred.resolve(note);
+ const $noteEl = $notesContainer.find(`#note_${note.id}`);
+ $noteEl.find('.js-note-edit').click();
+ $noteEl.find('textarea.js-note-text').html(updatedComment);
+ $noteEl.find('.js-comment-save-button').click();
+
+ const $updatedNoteEl = $notesContainer.find(`#note_${note.id}`).find('.js-task-list-container');
+ expect($updatedNoteEl.find('.note-text').text().trim()).toEqual('');
+ });
+ });
+
describe('getFormData', () => {
it('should return form metadata object from form reference', () => {
this.notes = new Notes('', []);