aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsilverwind <me@silverwind.io>2020-08-22 14:36:56 +0200
committerGitHub <noreply@github.com>2020-08-22 13:36:56 +0100
commitee5e5a50934906df476c3b898c2fe8e0df984f3c (patch)
treea4f3a6c30e862ca77bb509d122cdfc04912e258a
parent03ba12aabf95ced8398c7859deff76780a4577cd (diff)
downloadgitea-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.json5
-rw-r--r--package.json1
-rw-r--r--web_src/js/index.js17
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
});
});