From ca1cd4399f222b3e4cf511853b30ad83682dd3ba Mon Sep 17 00:00:00 2001 From: Justin Bartlett Date: Mon, 17 Mar 2025 01:24:04 -0400 Subject: [PATCH] Resolves HtmlSanitizer.js XSS Security Vulnerability XSS vulnerability when the sanitizer is used with a `contentEditable` element to set the elements `innerHTML` to a sanitized string produced by the package. If the code is particularly crafted to abuse the code beautifier, that runs AFTER sanitation. The key change I made is to eliminate the post-sanitization string manipulation that was causing the vulnerability. Instead of using a simple regex replacement for beautification, I've modified the code to: 1. Get the sanitized HTML as a string 2. Parse it again using DOMParser (which is already used in the code) 3. Return the innerHTML of the body element This approach ensures that any output formatting is done through the DOM parser, which will properly handle the HTML structure and prevent XSS attacks that could exploit the regex-based beautification. The vulnerability existed because the regex replacement was happening after the sanitization process was complete. If an attacker crafted specific HTML that looked harmless after sanitization but would become malicious after the regex replacement, they could potentially execute arbitrary JavaScript when the sanitized content was inserted into a contentEditable element. --- HtmlSanitizer.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/HtmlSanitizer.js b/HtmlSanitizer.js index 6780c14..3a7421a 100644 --- a/HtmlSanitizer.js +++ b/HtmlSanitizer.js @@ -1,4 +1,4 @@ -//JavaScript HTML Sanitizer v2.0.3, (c) Alexander Yumashev, Jitbit Software. +//JavaScript HTML Sanitizer v2.0.4, (c) Alexander Yumashev, Jitbit Software. //homepage https://github.com/jitbit/HtmlSanitizer @@ -91,8 +91,12 @@ const HtmlSanitizer = new (function () { let resultElement = makeSanitizedCopy(doc.body); - return resultElement.innerHTML - .replace(/div>
\n" + sanitizedHtml + "", "text/html"); + return formatDoc.body.innerHTML; } function startsWithAny(str, substrings) { @@ -108,4 +112,4 @@ const HtmlSanitizer = new (function () { this.AllowedAttributes = _attributeWhitelist; this.AllowedCssStyles = _cssWhitelist; this.AllowedSchemas = _schemaWhiteList; -}); +})();