[s] Fixes XSS Exploit Defeating Sanitization of Any String in Goonchat (#49867)

* fix

* cleanup

* renamed that one function

* fixes for users who do not have 5 entries
This commit is contained in:
Bobbahbrown
2020-03-11 09:29:37 +13:00
committed by GitHub
parent f5cb1d471b
commit 8ba15b5ea8
@@ -79,12 +79,6 @@ function clamp(val, min, max) {
return Math.max(min, Math.min(val, max))
}
function outerHTML(el) {
var wrap = document.createElement('div');
wrap.appendChild(el.cloneNode(true));
return wrap.innerHTML;
}
//Polyfill for fucking date now because of course IE8 and below don't support it
if (!Date.now) {
Date.now = function now() {
@@ -183,57 +177,62 @@ function replaceRegex() {
$(this).removeAttr('replaceRegex');
}
//Actually turns the highlight term match into appropriate html
function addHighlightMarkup(match) {
// Get a highlight markup span
function createHighlightMarkup() {
var extra = '';
if (opts.highlightColor) {
extra += ' style="background-color: '+opts.highlightColor+'"';
extra += ' style="background-color: ' + opts.highlightColor + '"';
}
return '<span class="highlight"'+extra+'>'+match+'</span>';
return '<span class="highlight"' + extra + '></span>';
}
//Highlights words based on user settings
// Get all child text nodes that match a regex pattern
function getTextNodes(elem, pattern) {
var result = $([]);
$(elem).contents().each(function(idx, child) {
if (child.nodeType === 3 && /\S/.test(child.nodeValue) && pattern.test(child.nodeValue)) {
result = result.add(child);
}
else {
result = result.add(getTextNodes(child, pattern));
}
});
return result;
}
// Highlight all text terms matching the registered regex patterns
function highlightTerms(el) {
if (el.children.length > 0) {
for(var h = 0; h < el.children.length; h++){
highlightTerms(el.children[h]);
}
}
var pattern = new RegExp("(" + opts.highlightTerms.join('|') + ")", 'gi');
var nodes = getTextNodes(el, pattern);
var hasTextNode = false;
for (var node = 0; node < el.childNodes.length; node++)
{
if (el.childNodes[node].nodeType === 3)
{
hasTextNode = true;
break;
}
}
if (hasTextNode) { //If element actually has text
var newText = '';
for (var c = 0; c < el.childNodes.length; c++) { //Each child element
if (el.childNodes[c].nodeType === 3) { //Is it text only?
var words = el.childNodes[c].data.split(' ');
for (var w = 0; w < words.length; w++) { //Each word in the text
var newWord = null;
for (var i = 0; i < opts.highlightTerms.length; i++) { //Each highlight term
if (opts.highlightTerms[i] && words[w].toLowerCase().indexOf(opts.highlightTerms[i].toLowerCase()) > -1) { //If a match is found
newWord = words[w].replace("<", "&lt;").replace(new RegExp(opts.highlightTerms[i], 'gi'), addHighlightMarkup);
break;
}
if (window.console)
console.log(newWord)
}
newText += newWord || words[w].replace("<", "&lt;");
newText += w >= words.length ? '' : ' ';
}
} else { //Every other type of element
newText += outerHTML(el.childNodes[c]);
nodes.each(function (idx, node) {
var content = $(node).text();
var parent = $(node).parent();
var pre = $(node.previousSibling);
$(node).remove();
content.split(pattern).forEach(function (chunk) {
// Get our highlighted span/text node
var toInsert = null;
if (pattern.test(chunk)) {
var tmpElem = $(createHighlightMarkup());
tmpElem.text(chunk);
toInsert = tmpElem;
}
}
el.innerHTML = newText;
}
else {
toInsert = document.createTextNode(chunk);
}
// Insert back into our element
if (pre.length == 0) {
var result = parent.prepend(toInsert);
pre = $(result[0].firstChild);
}
else {
pre.after(toInsert);
pre = $(pre[0].nextSibling);
}
});
});
}
function iconError(E) {
@@ -421,7 +420,7 @@ function output(message, flag) {
//Actually do the snap
//Stuff we can do after the message shows can go here, in the interests of responsiveness
if (opts.highlightTerms && opts.highlightTerms.length > 0) {
highlightTerms(entry);
highlightTerms($(entry));
}
}
@@ -756,15 +755,11 @@ $(function() {
internalOutput('<span class="internal boldnshit">Loaded ping display of: '+(opts.pingDisabled ? 'hidden' : 'visible')+'</span>', 'internal');
}
if (savedConfig.shighlightTerms) {
var savedTerms = $.parseJSON(savedConfig.shighlightTerms);
var actualTerms = '';
for (var i = 0; i < savedTerms.length; i++) {
if (savedTerms[i]) {
actualTerms += savedTerms[i] + ', ';
}
}
var savedTerms = $.parseJSON(savedConfig.shighlightTerms).filter(function (entry) {
return entry !== null && /\S/.test(entry);
});
var actualTerms = savedTerms.length != 0 ? savedTerms.join(', ') : null;
if (actualTerms) {
actualTerms = actualTerms.substring(0, actualTerms.length - 2);
internalOutput('<span class="internal boldnshit">Loaded highlight strings of: ' + actualTerms+'</span>', 'internal');
opts.highlightTerms = savedTerms;
}
@@ -1066,20 +1061,12 @@ $(function() {
$('body').on('submit', '#highlightTermForm', function(e) {
e.preventDefault();
var count = 0;
while (count < opts.highlightLimit) {
opts.highlightTerms = [];
for (var count = 0; count < opts.highlightLimit; count++) {
var term = $('#highlightTermInput'+count).val();
if (term) {
term = term.trim();
if (term === '') {
opts.highlightTerms[count] = null;
} else {
opts.highlightTerms[count] = term.toLowerCase();
}
} else {
opts.highlightTerms[count] = null;
if (term !== null && /\S/.test(term)) {
opts.highlightTerms.push(term.trim().toLowerCase());
}
count++;
}
var color = $('#highlightColor').val();