From ee5e5a50934906df476c3b898c2fe8e0df984f3c Mon Sep 17 00:00:00 2001 From: silverwind Date: Sat, 22 Aug 2020 14:36:56 +0200 Subject: [PATCH] Improve HTML escaping helper (#12562) The previous method did not escape single quotes which under some circumstances can lead to XSS vulnerabilites and the fact that it depends on jQuery is also not ideal. Replace it with a lightweight module. --- package-lock.json | 5 +++++ package.json | 1 + web_src/js/index.js | 17 +++++++---------- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2f1c5807360..87e6991dd90 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4007,6 +4007,11 @@ "es6-symbol": "^3.1.1" } }, + "escape-goat": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-3.0.0.tgz", + "integrity": "sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw==" + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", diff --git a/package.json b/package.json index ce14631d704..fe2c6193cc3 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "cssnano": "4.1.10", "domino": "2.1.5", "dropzone": "5.7.0", + "escape-goat": "3.0.0", "fast-glob": "3.2.2", "file-loader": "6.0.0", "fomantic-ui": "2.8.4", diff --git a/web_src/js/index.js b/web_src/js/index.js index 886520db633..6fe6d3777fb 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -6,6 +6,7 @@ import './publicpath.js'; import './polyfills.js'; import Vue from 'vue'; +import {htmlEscape} from 'escape-goat'; import 'jquery.are-you-sure'; import './vendor/semanticdropdown.js'; import {svg} from './utils.js'; @@ -25,10 +26,6 @@ import {createCodeEditor} from './features/codeeditor.js'; const {AppSubUrl, StaticUrlPrefix, csrf} = window.config; -function htmlEncode(text) { - return jQuery('
').text(text).html(); -} - let previewFileModes; const commentMDEditors = {}; @@ -532,12 +529,12 @@ function initCommentForm() { switch (input_id) { case '#milestone_id': $list.find('.selected').html(`${ - htmlEncode($(this).text())}`); + htmlEscape($(this).text())}`); break; case '#assignee_id': $list.find('.selected').html(`` + `${ - htmlEncode($(this).text())}`); + htmlEscape($(this).text())}`); } $(`.ui${select_id}.list .no-select`).addClass('hide'); $(input_id).val($(this).data('id')); @@ -1942,7 +1939,7 @@ function searchUsers() { $.each(response.data, (_i, item) => { let title = item.login; if (item.full_name && item.full_name.length > 0) { - title += ` (${htmlEncode(item.full_name)})`; + title += ` (${htmlEscape(item.full_name)})`; } items.push({ title, @@ -2223,7 +2220,7 @@ function initTemplateSearch() { // Parse the response from the api to work with our dropdown $.each(response.data, (_r, repo) => { filteredResponse.results.push({ - name: htmlEncode(repo.full_name), + name: htmlEscape(repo.full_name), value: repo.id }); }); @@ -3500,8 +3497,8 @@ function initIssueList() { return; } filteredResponse.results.push({ - name: `#${issue.number} ${htmlEncode(issue.title) - }
${htmlEncode(issue.repository.full_name)}
`, + name: `#${issue.number} ${htmlEscape(issue.title) + }
${htmlEscape(issue.repository.full_name)}
`, value: issue.id }); });