diff options
author | silverwind <me@silverwind.io> | 2020-08-22 14:36:56 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-22 13:36:56 +0100 |
commit | ee5e5a50934906df476c3b898c2fe8e0df984f3c (patch) | |
tree | a4f3a6c30e862ca77bb509d122cdfc04912e258a | |
parent | 03ba12aabf95ced8398c7859deff76780a4577cd (diff) | |
download | gitea-ee5e5a50934906df476c3b898c2fe8e0df984f3c.tar.gz gitea-ee5e5a50934906df476c3b898c2fe8e0df984f3c.zip |
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.
-rw-r--r-- | package-lock.json | 5 | ||||
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | web_src/js/index.js | 17 |
3 files changed, 13 insertions, 10 deletions
diff --git a/package-lock.json b/package-lock.json index 2f1c580736..87e6991dd9 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 ce14631d70..fe2c6193cc 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 886520db63..6fe6d3777f 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('<div />').text(text).html(); -} - let previewFileModes; const commentMDEditors = {}; @@ -532,12 +529,12 @@ function initCommentForm() { switch (input_id) { case '#milestone_id': $list.find('.selected').html(`<a class="item" href=${$(this).data('href')}>${ - htmlEncode($(this).text())}</a>`); + htmlEscape($(this).text())}</a>`); break; case '#assignee_id': $list.find('.selected').html(`<a class="item" href=${$(this).data('href')}>` + `<img class="ui avatar image" src=${$(this).data('avatar')}>${ - htmlEncode($(this).text())}</a>`); + htmlEscape($(this).text())}</a>`); } $(`.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) - }<div class="text small dont-break-out">${htmlEncode(issue.repository.full_name)}</div>`, + name: `#${issue.number} ${htmlEscape(issue.title) + }<div class="text small dont-break-out">${htmlEscape(issue.repository.full_name)}</div>`, value: issue.id }); }); |