Repository navigation
chore(deps): update dependency sanitize-html to v2.17.7 [security] - #271
Open
renovate[bot] wants to merge 1 commit into
Open
renovate[bot] wants to merge 1 commit into
renovate[bot] wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
2.17.0→2.17.7sanitize-html has incomplete URI scheme validation in that allows javascript: URIs through action, formaction, data, poster, and background attributes
CVE-2026-53606 / GHSA-vccv-cmxp-4j9h
More information
Details
Summary
sanitize-html uses
allowedSchemesAppliedToAttributes(default:['href', 'src', 'cite']) to gate thenaughtyHref()function that blocks dangerous URI schemes likejavascript:andvbscript:. 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
allowedSchemesAppliedToAttributeswhen 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.,action). Default configuration is NOT vulnerable. However, this is a common configuration pattern for CMS platforms, form builders, and rich content editors.Affected Versions
All versions of sanitize-html from v1.18.0 (which introduced
allowedSchemesAppliedToAttributes) through at least v2.17.2. The default list has been['href', 'src', 'cite']since introduction and has never been expanded.Root Cause
File:
index.js:329(sanitize-html 2.10.0, confirmed same in 2.17.x)Default list at line 829:
The
naughtyHref()function (lines 627-667) correctly blocksjavascript:,vbscript:, and other dangerous schemes. However, it has exactly 2 call sites in the entire codebase (lines 330 and 395), both inside theindexOfgate. There is no ungated path.When attribute name is
action,formaction,data,poster,background, etc.:indexOf('action')returns-1ifblock is skipped entirelynaughtyHref()is never calledjavascript:alert(1)passes through unmodifiedThe
escapeHtml()function at line 464 provides no defense — it only encodes& < > "characters, which are not present injavascript:alert(1).Data Flow:
Steps to Reproduce
Observed behavior:
javascript:preserved onaction/formaction/databut correctly stripped onhref.Expected behavior:
javascript:should be stripped on ALL URI-bearing attributes, or at minimum, the library should warn developers when they allow URI-bearing attributes not covered by scheme validation.Impact
An attacker can achieve XSS in applications that use sanitize-html with non-default configurations allowing URI-bearing attributes:
<form action="javascript:...">— XSS on form submission (all modern browsers)<button formaction="javascript:...">— per-button XSS override (all modern browsers)<object data="javascript:...">— object load XSS (Chrome, Firefox)<video poster="javascript:...">— limited browser support but spec-validCommon vulnerable configurations:
Mitigating factors:
form-actiondirective mitigates form-based vectorsallowedSchemesAppliedToAttributesRemediation
Option 1 (Recommended): Expand the default
allowedSchemesAppliedToAttributeslist:Option 2: Apply
naughtyHref()to ALL attributes by default (invert the gate logic).Option 3: Add a runtime warning when developers allow URI-bearing attributes not in
allowedSchemesAppliedToAttributes(analogous tovulnerableTagswarning forscript/styleat lines 124-129).Reporter
Kevin Lee (Changseon Lee)
OPCIA Corp. / PeanutAI Inc.
Seoul, South Korea
GitHub: crattack
Severity
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
ApostropheCMS: Stored XSS via SVG SMIL URI-list scheme-policy bypass
CVE-2026-84371 / GHSA-g8qq-57p8-ggw5
More information
Details
Summary
When SVG animation is allowed,
attributeName="href"makesvaluesa list of URL destinations.sanitize-htmlaccepts a list that starts with a safe fragment even whenvaluesis explicitly scheme-checked, allowing a laterjavascript:destination to execute when the sanitized link is activated.Details
index.js:371-383validates each attribute as one flat URL. It does not recognize thatattributeName="href"gives the siblingvaluesattribute SMIL URI-list semantics. Forvalues="#safe;javascript:...", the leading fragment passes the flat check and the complete list is retained.PoC
This was reproduced with
sanitize-html@2.17.6and Chromium 150.0.7871.124. The configuration adds SVG animation to the defaults and applies the existing scheme policy tovalues; it does not allowjavascript:. Save this aspoc.js:Install and run it, then open
poc.htmland clickClick me:npm install sanitize-html@2.17.6 node poc.js > poc.htmlThe output retains the
javascript:entry, and clicking the sanitized SVG displaysXSS. Withinputchanged to<a href="javascript:alert(1)">control</a>, the same configuration removeshref.Impact
In an application that accepts attacker-authored SVG animation, the attacker can store this payload without scripts or event handlers. A victim who activates the sanitized link executes JavaScript in the application's origin despite the configured scheme policy.
Suggested fix
Reject
attributeNamevalues selectinghreforxlink:hrefon SVGanimateandset, while retaining safe targets such asfill. Addvalues,from, andtoregression cases.Severity
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
ApostropheCMS: Mutation-XSS / allowedTags bypass via literal
</textarea/>solidus closeCVE-2026-63670 / GHSA-jxwj-j7wr-gfrw
More information
Details
Summary
A mutation-XSS / allowedTags bypass: when
textarea(orxmp) is included inallowedTags, 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 throughsanitizeHtml()live and unescaped, even thoughimg/onerrorare 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-htmlemits the text content of HTML raw-text elements (textarea,xmp) without escaping. Two things combine:</textarea/>(solidus after the RCDATAend-tag name) as a close tag; it emits
</textarea/><img …>as a single raw-text node.ontexthandler (index.js~575-583) appendstextarea/xmpcontent withresult += text(noescapeHtml), assuming it is "already properly encoded" — true for entity-decodedcontent (what CVE-2026-40186 fixed) but false for this mis-tokenized literal close tag.
A spec browser treats
</textarea/>as a validtextareaclose, so the following<img onerror>is parsed as a live element. The recent fixes addressed entity-encoding (CVE-2026-40186) and thexmpdefault (CVE-2026-44990); neither covers the literal-solidus mis-tokenization, so the raw passthrough still leaks.PoC
Re-parsing the sanitized OUTPUT with parse5 (the WHATWG HTML parser browsers/jsdom use) yields a live

<img src=x onerror=alert(document.domain)>atbodylevel (it escaped the textarea RCDATA, not inert text) → theonerrorfires in a browser. Confirmed on 2.17.5 (Node v24). A canonicalpoc.jsis attached.Impact
Cross-site scripting (CWE-79). Requires
textarea(orxmp) inallowedTags— a benign-looking, common addition in form builders, CMS, and rich-text editors. Adding a harmless tag that then enables XSS via non-allowedimg/onerrorbreaks the sanitizer's core contract; the maintainers have fixed this class before (e.g. GHSA-9mrh). An attacker who can submit content rendered through such a configuration achieves stored/reflected XSS (cookie theft, session hijack). Severity Medium (default config is safe; user interaction to view the page). Suggested fix: routetextarea/xmpcontent throughescapeHtmlinstead of the raw passthrough, and/or fix the htmlparser2</tag/>RCDATA end-tag tokenization to match the WHATWG spec.Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Release Notes
apostrophecms/apostrophe (sanitize-html)
v2.17.7Compare Source
Security
animate,animateColor,animateMotion,animateTransformorset) together withattributeNameand one of the animation value attributes. The default configuration was not affected, as these elements are not in the defaultallowedTags.apostrophecmswas not affected. Thanks to koyokr for responsibly disclosing the vulnerability (GHSA-g8qq-57p8-ggw5).v2.17.6Compare Source
Adds
loggeroption: pass any console-shaped object, withdebug,info,warnanderrormethods, and sanitize-html's own diagnostics are delivered to it rather than to the console, so an application with a logging pipeline of its own can route them. Missing methods, and no option at all, fall back to the console. Those messages also lost their decorative line breaks and warning icon, so each is now a single line of text; their wording is otherwise unchanged.Fixes
allowedSchemesByTagis now applied tosrcsetandimagesrcsetURLs. Previously the per-tag lookup used the attribute name instead of the tag name, so these attributes always fell back to the globalallowedSchemesand ignored a tag-specific scheme allowlist. Thanks tospokodev for the fix.
sanitize-htmlbegan escaping any markup preserved inside a disallowed iframe tag, which was a changein behavior due to an upstream change in
htmlparser2. This fix ensures such "fallback markup" is preserved without escaping, but alsofully sanitized according to the same rules as the original input. Thanks to sumitjhacodes for
the fix.
Security
When
metawas allowed together with itshttp-equivandcontentattributes, the destination URL of a<meta http-equiv="refresh" content="0;url=...">was never checked againstallowedSchemes, because it is embedded incontentrather than being an attribute of its own. Sojavascript:,data:and other disallowed destinations passed through. The refresh URL is now extracted the way browsers do it, allowing for the different spellings, separators, quoting and letter case ofurl=, and checked againstallowedSchemes(orallowedSchemesByTag.meta). If it is rejected, or the content cannot be parsed as a refresh, thecontentattribute is removed.contenton othermetaelements is unchanged. The default configuration does not allowmetaand was not affected (CWE-79, CWE-601, GHSA-cv27-6wvh-8x7j).Thanks to adrbogacz for reporting the vulnerability.
When
noscriptis listed innonTextTags, the discarded region could end too early. Browsers with scripting enabled treat<noscript>content as raw text up to the first</noscript>, but the underlying parser treats it as markup, so an end tag for an enclosing element inside<noscript>closed it implicitly and the rest of its content was emitted as ordinary sanitized markup. The discard region now continues until the point where a browser would end the<noscript>element, while implied closes of othernonTextTagssuch as<option>behave as before (CWE-79, CWE-436, GHSA-x3q4-9hxx-gx8m).Thanks to joaquiniglesiaslug for reporting the vulnerability.
The check that drops SVG animation elements (
animate,animateColor,animateMotion,animateTransform,set) when they retarget a URL attribute such ashrefcompared the full tag name, so a namespace-prefixed spelling likesvg:animatewas not recognized when such tags were allowed (for example withallowedTags: false). In XML serializations such as XHTML or standalone SVG, the prefixed element is a real animation element and could retarget a link to ajavascript:URL after sanitization. The element andattributeNameare now matched by their local names, ignoring any prefix (CWE-79, CWE-184, GHSA-374f-7chj-9948).Thanks to Kai Aizen (SnailSploit) for reporting the vulnerability.
v2.17.5Compare Source
Security
javascript:and similar. None of these are used in the default configuration ofsanitize-htmlorapostropheor likely to be used there, and some attributes, like anactionfor aform, are inherently unsafe to allow if XSS protection is your goal. Nevertheless it makes sense to block certain URL types where they are not appropriate. Some attributes are not supported at all by modern browsers but are included for completeness. Thanks to crattack for reporting the vulnerability.v2.17.4Compare Source
Changes
sanitize-htmlandlaundernow share a single implementation ofnaughtyHref, based on that which previously existed insanitize-html.Security
v2.17.3Compare Source
Security
optiontags. There was no vulnerability when not explicitly allowingoptiontags.v2.17.2Compare Source
Changes
htmlparser2from 8.x to 10.1.0. This improves security by correctly decoding zero-padded numeric character references (e.g.,&#​0000001) that previously bypassedjavascript:URL detection. Also fixes double-encoding of entities inside raw text elements liketextareaandoption.v2.17.1Compare Source
Fixes
<hello) returning empty string inescapeandrecursiveEscapemodes. Fixes #706.Thanks to Byeong Hyeon for the fix.
Configuration
📅 Schedule: (UTC)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.