diff --git a/src/HtmlUtils.js b/src/HtmlUtils.js index fc1630b6fb..ae594de960 100644 --- a/src/HtmlUtils.js +++ b/src/HtmlUtils.js @@ -28,6 +28,11 @@ emojione.imagePathSVG = 'emojione/svg/'; emojione.imageType = 'svg'; const EMOJI_REGEX = new RegExp(emojione.unicodeRegexp+"+", "gi"); +const COLOR_REGEX = /^[#a-z0-9]+$/; +const ALLOWED_CSS = { + "background-color": COLOR_REGEX, + "color": COLOR_REGEX, +}; /* modified from https://github.com/Ranks/emojione/blob/master/lib/js/emojione.js * because we want to include emoji shortnames in title text @@ -91,7 +96,7 @@ var sanitizeHtmlParams = { ], allowedAttributes: { // custom ones first: - font: [ 'color' ], // custom to matrix + font: [ 'color' , 'style' ], // custom to matrix a: [ 'href', 'name', 'target', 'rel' ], // remote target: custom to matrix // We don't currently allow img itself by default, but this // would make sense if we did @@ -136,6 +141,31 @@ var sanitizeHtmlParams = { attribs.rel = 'noopener'; // https://mathiasbynens.github.io/rel-noopener/ return { tagName: tagName, attribs : attribs }; }, + '*': function(tagName, attribs) { + // Only allow certain CSS attributes to avoid XSS attacks + // Sanitizing values to avoid `url(...)` and `expression(...)` attacks + if (!attribs.style) { + return { tagName: tagName, attribs : attribs }; + } + + const pairs = attribs.style.split(';'); + let sanitisedStyle = ""; + for (let i = 0; i < pairs.length; i++) { + const pair = pairs[i].split(':'); + if (!Object.keys(ALLOWED_CSS).includes(pair[0]) || !ALLOWED_CSS[pair[0]].test(pair[1])) { + continue; + } + sanitisedStyle += pair[0] + ":" + pair[1] + ";"; + } + + if (sanitisedStyle) { + attribs.style = sanitisedStyle; + } else { + delete attribs.style; + } + + return { tagName: tagName, attribs : attribs }; + }, }, };