Overview
A critical cross-site scripting (XSS) vulnerability has been disclosed in sanitize-html, the widely used Node.js HTML sanitization library. Tracked as CVE-2026-44990 with a CVSS score of 9.3, the flaw allows attacker-controlled content inside a disallowed xmp element to escape sanitization and render as live HTML in the browser.
The vulnerability affects all versions of sanitize-html prior to 2.17.4 and is particularly impactful for applications built on ApostropheCMS, which depends on sanitize-html for content sanitization.
Technical Details
The xmp element is an obsolete HTML tag originally designed to display raw, preformatted text without processing HTML entities or tags. Modern browsers still parse the xmp element but handle its content in a parser-dependent manner.
When sanitize-html is configured to disallow the xmp tag (which is the default for most configurations), the library strips the xmp opening and closing tags but does not properly escape the raw content within them before outputting it. This means that HTML markup embedded inside an xmp element by an attacker passes through the sanitizer as literal text—which browsers then interpret and render as active HTML.
Attack scenario:
An attacker who can inject HTML into a field sanitized by the affected library (e.g., a comment field, rich-text editor, or user bio) can submit content such as:
<xmp><script>alert(document.cookie)</script></xmp>After sanitization with a vulnerable version, the output becomes:
<script>alert(document.cookie)</script>This executes in the victim's browser context, enabling session hijacking, credential theft, or malicious redirects.
Affected Versions
| Package | Affected Versions | Fixed Version |
|---|---|---|
| sanitize-html | < 2.17.4 | 2.17.4 |
| ApostropheCMS | Versions depending on sanitize-html < 2.17.4 | Update sanitize-html dependency |
CVSS Score
| Metric | Value |
|---|---|
| Score | 9.3 (Critical) |
| Attack Vector | Network |
| Attack Complexity | Low |
| Privileges Required | None |
| User Interaction | Required |
| Confidentiality | High |
| Integrity | High |
| Availability | None |
Impact
Successful exploitation enables:
- Stored XSS in any application that stores and re-renders user-supplied content sanitized by the affected library
- Session hijacking via cookie theft if the
HttpOnlyflag is not set - Credential harvesting through phishing overlays injected into legitimate pages
- Account takeover in CMS environments where editors and admins view user-submitted content
- Malware distribution via injected script tags that redirect users to attacker-controlled payloads
Applications processing user-generated content—such as blog comments, forum posts, or rich text fields—are particularly at risk.
Remediation
Immediate Actions
- Update sanitize-html to version 2.17.4 or later:
npm update sanitize-html
# or explicitly
npm install sanitize-html@2.17.4-
Verify your package-lock.json or
yarn.lockreflects the updated version. -
ApostropheCMS users should update the
sanitize-htmldependency in their project and confirm the CMS itself has published an updated release that pins to 2.17.4+.
Verify Installed Version
npm list sanitize-htmlEnsure the resolved version is 2.17.4 or higher. If transitive dependencies resolve an older version, use npm overrides to force the patched version:
{
"overrides": {
"sanitize-html": "^2.17.4"
}
}Workaround (If Patching is Delayed)
Add xmp to the list of explicitly disallowed tags with aggressive stripping, and add a post-processing step to escape any remaining raw HTML entities. However, this is not a guaranteed mitigation—updating to the fixed version is strongly recommended.
Detection
Review your application logs for xmp tags appearing in submitted user content. Audit stored content in your database for any existing payloads using this vector. Search for <xmp in user-generated HTML fields.