Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
📦
📦 npm
Not in CISA KEV
LOW severity

CVE-2026-113657 — sanitize-html

LOWFix: apostrophecms/apostrophe@9500b8b

CVE-2026-113657 is a low-severity (CVSS 3.7) Cross-site Scripting (XSS) vulnerability in sanitize-html. A fix is available for sanitize-html — see the affected versions and patch details below.

ApostropheCMS sanitize-html: SMIL animation namespace-prefix bypass allows javascript: URI injection (XSS)

Also known asGHSA-374f-7chj-9948
Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Oct 22, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-113657.

EPSS Exploitation Probability

via FIRST.org ↗
0.3%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs23th percentile — riskier than 23% of all scored CVEsHighest risk

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

CVE-2026-113657 by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.

Where this sits among everything scored

Of 394,803 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.

Real-World Exposure

1 pkg affected
📦sanitize-html

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects npm packages — download data is not available via public APIs for these ecosystems.

Description

Summary

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 itself.

Proof of Concept

const sanitizeHtml = require("sanitize-html");

const config = {
  allowedTags: false,
  allowedAttributes: false,
  allowedSchemes: ["http", "https"]
};

// Standard animate — BLOCKED by 2.17.7 fix
const blocked = sanitizeHtml(
  `<svg><a href="#safe"><animate attributeName="href" values="#safe;javascript:alert(1)" dur=".01s" fill="freeze"/><text>Click</text></a></svg>`,
  config
);
console.log("Standard animate:", blocked.includes("javascript:") ? "BYPASS" : "BLOCKED");
// Output: BLOCKED

// Namespace-prefixed animate — BYPASSES the fix
const bypassed = sanitizeHtml(
  `<svg><a href="#safe"><svg:animate attributeName="href" values="#safe;javascript:alert(document.domain)" dur=".01s" fill="freeze"/><text>Click</text></a></svg>`,
  config
);
console.log("svg:animate:", bypassed.includes("javascript:") ? "BYPASS" : "BLOCKED");
// Output: BYPASS

All 5 SMIL animation elements are bypassable with any namespace prefix (svg:, xlink:, xml:, uppercase variants). Tested and confirmed on sanitize-html 2.17.7 from the apostrophe monorepo.

Impact

Cross-site scripting (XSS) via SMIL animation retargeting. When an application uses allowedTags: false (common in rich-text editors that want to preserve SVG), an attacker can inject <svg:animate attributeName="href" values="#safe;javascript:..." .../> to override the href attribute of a parent <a> element after the page loads, causing the link to execute JavaScript when clicked.

Suggested Fix

Strip the namespace prefix from the tag name before the lookup, matching the pattern already used for the attribute name target:

// Before (vulnerable):
if (svgAnimationTags.indexOf(name.toLowerCase()) === -1) {

// After (fixed):
const localTagName = name.toLowerCase().slice(name.lastIndexOf(":") + 1);
if (svgAnimationTags.indexOf(localTagName) === -1) {

Affected Versions

sanitize-html >= 2.17.7 (where the SMIL animation protection was introduced). Earlier versions lack the SMIL protection entirely.

Credit

Kai Aizen (SnailSploit) — Adversarial AI & Security Research

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
📦npmsanitize-html≥ 2.17.7&&< 2.18.02.18.0npm install sanitize-html@2.18.0

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for sanitize-html, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update sanitize-html to 2.18.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-113657 is resolved across your whole dependency graph.

  3. Workarounds

    Escape or sanitise the affected output on the server side rather than relying on client-side filtering, and add a Content-Security-Policy that blocks inline script execution so injected markup cannot run even if it reaches the page.

Fixing This On Your OS

If you run this on a Linux distribution, patch through your package manager against the distro's own security advisory below — it tracks the exact backported fix for your release, which can ship on a different timeline (and sometimes a different severity) than the upstream project.

Red HatLow

This vulnerability is rated as Low impact for Red Hat products because triggering the flaw requires non-default, permissive sanitization policies that explicitly allow SVG animation markup and attributes. Exploitation additionally relies on user interaction, requiring a victim to click a maliciously manipulated link…

Workaround published by Red Hat
Mitigation for this issue is either not available or the currently available options do not meet the Red Hat Product Security criteria comprising ease of use and deployment, applicability to widespread installation base, or stability.
Source: Red Hat security advisory for CVE-2026-113657 (CC BY 4.0)

Frequently Asked Questions

## Summary 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", "animatetransf
O3 Security · Impact-Aware SCA

Is CVE-2026-113657 in your dependencies?

Find it across npm, including transitive dependencies.

CVE-2026-113657: sanitize-html XSS — Fixed in 2.18.0