Improve HTML escaping helper (#12383)
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. Co-authored-by: techknowlogick <techknowlogick@gitea.io>
This commit is contained in:
parent
24f8625790
commit
11dcc17763
3 changed files with 13 additions and 10 deletions
5
package-lock.json
generated
5
package-lock.json
generated
|
@ -4372,6 +4372,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.0.2.tgz",
|
||||||
"integrity": "sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ=="
|
"integrity": "sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ=="
|
||||||
},
|
},
|
||||||
|
"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": {
|
"escape-string-regexp": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
"css-loader": "4.0.0",
|
"css-loader": "4.0.0",
|
||||||
"cssnano-webpack-plugin": "1.0.3",
|
"cssnano-webpack-plugin": "1.0.3",
|
||||||
"dropzone": "5.7.2",
|
"dropzone": "5.7.2",
|
||||||
|
"escape-goat": "3.0.0",
|
||||||
"fast-glob": "3.2.4",
|
"fast-glob": "3.2.4",
|
||||||
"file-loader": "6.0.0",
|
"file-loader": "6.0.0",
|
||||||
"fomantic-ui": "2.8.6",
|
"fomantic-ui": "2.8.6",
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import './publicpath.js';
|
import './publicpath.js';
|
||||||
|
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
import {htmlEscape} from 'escape-goat';
|
||||||
import 'jquery.are-you-sure';
|
import 'jquery.are-you-sure';
|
||||||
import './vendor/semanticdropdown.js';
|
import './vendor/semanticdropdown.js';
|
||||||
|
|
||||||
|
@ -25,10 +26,6 @@ import {svg, svgs} from './svg.js';
|
||||||
|
|
||||||
const {AppSubUrl, StaticUrlPrefix, csrf} = window.config;
|
const {AppSubUrl, StaticUrlPrefix, csrf} = window.config;
|
||||||
|
|
||||||
function htmlEncode(text) {
|
|
||||||
return jQuery('<div />').text(text).html();
|
|
||||||
}
|
|
||||||
|
|
||||||
let previewFileModes;
|
let previewFileModes;
|
||||||
const commentMDEditors = {};
|
const commentMDEditors = {};
|
||||||
|
|
||||||
|
@ -528,12 +525,12 @@ function initCommentForm() {
|
||||||
switch (input_id) {
|
switch (input_id) {
|
||||||
case '#milestone_id':
|
case '#milestone_id':
|
||||||
$list.find('.selected').html(`<a class="item" href=${$(this).data('href')}>${
|
$list.find('.selected').html(`<a class="item" href=${$(this).data('href')}>${
|
||||||
htmlEncode($(this).text())}</a>`);
|
htmlEscape($(this).text())}</a>`);
|
||||||
break;
|
break;
|
||||||
case '#assignee_id':
|
case '#assignee_id':
|
||||||
$list.find('.selected').html(`<a class="item" href=${$(this).data('href')}>` +
|
$list.find('.selected').html(`<a class="item" href=${$(this).data('href')}>` +
|
||||||
`<img class="ui avatar image" src=${$(this).data('avatar')}>${
|
`<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');
|
$(`.ui${select_id}.list .no-select`).addClass('hide');
|
||||||
$(input_id).val($(this).data('id'));
|
$(input_id).val($(this).data('id'));
|
||||||
|
@ -1944,7 +1941,7 @@ function searchUsers() {
|
||||||
$.each(response.data, (_i, item) => {
|
$.each(response.data, (_i, item) => {
|
||||||
let title = item.login;
|
let title = item.login;
|
||||||
if (item.full_name && item.full_name.length > 0) {
|
if (item.full_name && item.full_name.length > 0) {
|
||||||
title += ` (${htmlEncode(item.full_name)})`;
|
title += ` (${htmlEscape(item.full_name)})`;
|
||||||
}
|
}
|
||||||
items.push({
|
items.push({
|
||||||
title,
|
title,
|
||||||
|
@ -2220,7 +2217,7 @@ function initTemplateSearch() {
|
||||||
// Parse the response from the api to work with our dropdown
|
// Parse the response from the api to work with our dropdown
|
||||||
$.each(response.data, (_r, repo) => {
|
$.each(response.data, (_r, repo) => {
|
||||||
filteredResponse.results.push({
|
filteredResponse.results.push({
|
||||||
name: htmlEncode(repo.full_name),
|
name: htmlEscape(repo.full_name),
|
||||||
value: repo.id
|
value: repo.id
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -3500,8 +3497,8 @@ function initIssueList() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
filteredResponse.results.push({
|
filteredResponse.results.push({
|
||||||
name: `#${issue.number} ${htmlEncode(issue.title)
|
name: `#${issue.number} ${htmlEscape(issue.title)
|
||||||
}<div class="text small dont-break-out">${htmlEncode(issue.repository.full_name)}</div>`,
|
}<div class="text small dont-break-out">${htmlEscape(issue.repository.full_name)}</div>`,
|
||||||
value: issue.id
|
value: issue.id
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Reference in a new issue