Open actionable advisories and recorded vendor fixes. This public package view has no inventory attached and cannot establish whether your deployment is affected. A vendor fix never resolves your finding; verify your installed version and the source guidance.
Open advisories
17 actionable advisories, newest first. Withdrawn advisories and news are excluded. Coverage is partial.
Since 2.18.0, when an <iframe is not allowed and disallowedTagsMode is 'discard' (the defaults), its raw-text content is re-sanitized by a recursive call to sanitizeHtml(text, options) (the change from #5564, fixing #5550). The recursion has no bound and starts each nested call with a fresh state. Two consequences, both absent from 2.17.7 and 2.17.4: 1. A few kilobytes of unclosed <iframe tags throw RangeError: Maximum call stack size exceeded with the default options. Any application that sanitizes untrusted HTML with 2.18.0 can be made to throw on a small crafted input. 2. nestingLimit is not enforced across a discarded iframe: each nested iframe restarts the depth count at zero, so the output can be nested arbitrarily deep regardless of the configured limit. Affected versions - 2.18.0 (the current latest), and the main branch at the time of writing (the recursive call is still in packages/sanitize-html/index.js, in the ontext handler, branch tag === 'iframe' &&…
Recommended action: Upgrade to 2.18.1 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
sanitize-html 2.17.7 introduced animatesUrlAttribute() to block SVG animation elements (animate, animateColor, animateMotion, animateTransform, set) when their attributeName targets a URL sink like href. However, this check is bypassed when the animation element uses a namespace prefix (e.g., svg:animate instead of animate). Root Cause The animatesUrlAttribute function (index.js, line ~832) checks svgAnimationTags.indexOf(name.toLowerCase()), where svgAnimationTags contains bare local names: ["animate", "animatecolor", "animatemotion", "animatetransform", "set"]. htmlparser2 passes namespace-prefixed tag names verbatim, so svg:animate does not match animate in the array, causing the function to return false and skip the SMIL XSS protection. Ironically, the function already handles namespace prefixes correctly for the attributeName target value (line ~843): const localName = target.slice(target.lastIndexOf(":") + 1) — but this same stripping was not applied to the tag name…
Recommended action: Upgrade to 2.18.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
CVE-2026-53606 expanded allowedSchemesAppliedToAttributes so named URL attributes (action, formaction, data, poster, background, later ping, xlink:href, …) go through naughtyHref(). A URL nested inside meta content (http-equiv=refresh) is not an attribute name on that list, so the embedded destination is never scheme-checked. Default allowedTags still omit meta. Same non-default integrator config as 53606: allow meta plus http-equiv / content. On 2.17.7: data:text/html,… and arbitrary https: destinations also survive. formaction="javascript:…" (53606) is stripped. Please Request CVE. Credit: Finder + Reporter (adrbogacz). Details naughtyHref() only runs when the attribute name is in allowedSchemesAppliedToAttributes (index.js ~385). Refresh URLs live in a content value of the form 0;url=…, so the gate never fires. Adding content to that list wholesale would break ordinary meta content (description, viewport). Fix: when http-equiv is refresh (case-insensitive), parse the ;…
Recommended action: Upgrade to 2.18.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
sanitize-html discards the content of every element in nonTextTags. It delimits that region using htmlparser2's close events, and ignores the isImplied flag htmlparser2 passes it. Closing a still-open ancestor from inside a <noscript makes htmlparser2 unwind its stack past the noscript; the synthetic implied close it emits on the way ends the discard region early, and everything after it is treated as ordinary body content. A browser with scripting enabled parses <noscript content as raw text, so the same markup renders as inert text there. The sanitizer therefore emits elements the page itself would not have. Reproduction Chrome, given the same input, renders no <img — the whole payload is raw text inside the unclosed <noscript. Verified with Playwright, srcdoc into an iframe so the scripting flag is on. A <![CDATA[ variant hides the opening tag from the parser entirely and has the same effect: htmlparser2 runs a CDATA token to ]]; Chrome ends a bogus comment at the first ,…
Recommended action: Upgrade to 2.18.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
A mutation-XSS / allowedTags bypass: when textarea (or xmp) is included in allowedTags, an input containing a literal </textarea/ (a solidus right after the RCDATA end-tag name) lets non-allowed markup such as <img src=x onerror=… pass through sanitizeHtml() live and unescaped, even though img/onerror are not in the allowlist. A spec-compliant browser executes the surviving handler — XSS. This is a literal-solidus variant that bypasses the two most recent fixes in this code area (CVE-2026-40186, CVE-2026-44990), both already applied in 2.17.5. The default configuration is not affected. Details sanitize-html emits the text content of HTML raw-text elements (textarea, xmp) without escaping. Two things combine: - Parser differential: on input, htmlparser2 does NOT recognize </textarea/ (solidus after the RCDATA end-tag name) as a close tag; it emits </textarea/<img … as a single raw-text node. - Unescaped passthrough: the ontext handler (index.js ~575-583) appends textarea/xmp…
Recommended action: Upgrade to 2.17.6 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
When SVG animation is allowed, attributeName="href" makes values a list of URL destinations. sanitize-html accepts a list that starts with a safe fragment even when values is explicitly scheme-checked, allowing a later javascript: destination to execute when the sanitized link is activated. Details index.js:371-383 validates each attribute as one flat URL. It does not recognize that attributeName="href" gives the sibling values attribute SMIL URI-list semantics. For values="#safe;javascript:...", the leading fragment passes the flat check and the complete list is retained. PoC This was reproduced with sanitize-html@2.17.6 and Chromium 150.0.7871.124. The configuration adds SVG animation to the defaults and applies the existing scheme policy to values; it does not allow javascript:. Save this as poc.js: Install and run it, then open poc.html and click Click me: The output retains the javascript: entry, and clicking the sanitized SVG displays XSS. With input changed to <a…
Recommended action: Upgrade to 2.17.7 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
sanitize-html uses allowedSchemesAppliedToAttributes (default: ['href', 'src', 'cite']) to gate the naughtyHref() function that blocks dangerous URI schemes like javascript: and vbscript:. The HTML specification defines 10+ attributes that accept URIs (action, formaction, data, poster, background, ping, xlink:href, dynsrc, lowsrc), but none of these are included in the default gate list. When a developer allows any of these attributes in their configuration, javascript: URIs pass through completely unmodified, enabling XSS. The library has zero awareness of these URI-bearing attributes — none appear anywhere in the 854-line source file (verified by grep). No warning mechanism exists, and the README provides no security guidance about expanding allowedSchemesAppliedToAttributes when allowing form or media attributes. Severity Exploitation requires non-default configuration: the developer must explicitly allow a non-default tag (e.g., form) AND a non-default attribute (e.g.,…
Recommended action: Upgrade to 2.17.5 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Under the default configuration, sanitize-html can turn attacker-controlled content inside a disallowed xmp element into live HTML or JavaScript. This is a sanitizer bypass in the default disallowedTagsMode: 'discard' path and can lead to stored XSS in applications that render sanitized output back to users. Details In sanitize-html@2.17.3, the default nonTextTags list includes only script, style, textarea, and option in index.js lines 138-142. That means disallowed xmp tags are not treated as "drop the entire contents" tags. Later, in the ontext handler at index.js lines 569-577, the code special-cases textarea and xmp and appends their text content directly to the output without escaping: Because htmlparser2 treats xmp as a raw-text element, markup inside xmp is parsed as text on input but becomes live markup again once it is appended unescaped to the sanitized output. This creates a default sanitizer bypass. For example, a disallowed <xmp wrapper can be used to smuggle…
Recommended action: Upgrade to 2.17.4 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Commit 49d0bb7 introduced a regression in sanitize-html that bypasses allowedTags enforcement for text inside nonTextTagsArray elements (textarea and option). Entity-encoded HTML inside these elements passes through the sanitizer as decoded, unescaped HTML, allowing injection of arbitrary tags including XSS payloads. This affects any application using sanitize-html that includes option or textarea in its allowedTags configuration. Details The vulnerable code is at packages/sanitize-html/index.js:569-573: The comment is factually incorrect. htmlparser2 10.x does decode HTML entities inside both <textarea and <option elements before passing text to the ontext callback. This can be verified: Because the code assumes the text is "already properly encoded" and skips escapeHtml(), the decoded entities (<, ) are written directly to the output as literal HTML characters. This completely bypasses the allowedTags filter — any tag can be injected inside an allowed option or textarea…
Recommended action: Upgrade to 2.17.3 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
sanitize-html prior to version 2.0.0-beta is vulnerable to Cross-site Scripting (XSS). The sanitizeHtml() function in index.js does not sanitize content when using the custom transformTags option, which is intended to convert attribute values into text. As a result, malicious input can be transformed into executable code.
Recommended action: Upgrade to 2.0.0-beta (pre-release) or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Versions of the package sanitize-html before 2.12.1 are vulnerable to Information Exposure when used on the backend and with the style attribute allowed, allowing enumeration of files in the system (including project dependencies). An attacker could exploit this vulnerability to gather details about the file system structure and dependencies of the targeted server.
Recommended action: Upgrade to 2.12.1 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
The package sanitize-html before 2.7.1 are vulnerable to Regular Expression Denial of Service (ReDoS) due to insecure global regular expression replacement logic of HTML comment removal.
Recommended action: Upgrade to 2.7.1 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Apostrophe Technologies sanitize-html before 2.3.2 does not properly validate the hostnames set by the "allowedIframeHostnames" option when the "allowIframeRelativeUrls" is set to true, which allows attackers to bypass hostname whitelist for iframe element, related using an src value that starts with "/\\example.com".
Recommended action: Upgrade to 2.3.2 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Apostrophe Technologies sanitize-html before 2.3.1 does not properly handle internationalized domain name (IDN) which could allow an attacker to bypass hostname whitelist validation set by the "allowedIframeHostnames" option.
Recommended action: Upgrade to 2.3.1 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Affected versions of sanitize-html do not sanitize input recursively, which may allow an attacker to execute arbitrary Javascript. Recommendation Update to version 1.4.3 or later.
Recommended action: Upgrade to 1.4.3 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Affected versions of sanitize-html are vulnerable to cross-site scripting when allowedTags includes at least one nonTextTag. Proof of Concept Recommendation Update to version 1.11.4 or later.
Recommended action: Upgrade to 1.11.4 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Affected versions of sanitize-html are vulnerable to cross-site scripting. Proof of Concept: <IMG SRC= onmouseover="alert('XSS');" produces the following: <img src="onmouseover="alert('XSS');"" / This is definitely invalid HTML, but would suggest that it's being interpreted incorrectly by the parser. Recommendation Update to version 1.2.3 or later.
Recommended action: Upgrade to 1.2.3 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.