DOMPurify: SAFE_FOR_TEMPLATES bypass lets template expressions survive in shadow root content on DOM output modes (GHSA-cg2g-xh64-v4q7)
Severity: critical · Patch status: patched · Since 2026-10-12 · CVE-2026-65900
DOMPurify 3.4.4 through 3.4.16 fails to scrub template expressions ({{...}}, ${...}, <%...%) inside attached shadow roots when SAFEFORTEMPLATES is enabled with a DOM-returning mode (RETURNDOM, RETURNDOMFRAGMENT, or INPLACE). The post-walk safety net scrubTemplateExpressions recurses into <template.content but not shadow roots, so an attacker-supplied expression split across text nodes separated by disallowed elements reassembles after sanitization and can be evaluated by a downstream template engine, yielding XSS or server-side template injection. Declarative shadow DOM via setHTMLUnsafe also reaches the gap. Exploitation requires non-default configuration and downstream template evaluation. Fixed in DOMPurify 3.4.17; a public proof of concept exists but no in-the-wild exploitation is known.
What to do
- Upgrade dompurify to 3.4.17 or later immediately if using SAFE_FOR_TEMPLATES with any DOM-returning mode
- Audit whether your app passes DOM nodes with attached shadow roots (including declarative shadow DOM parsed via setHTMLUnsafe/parseHTMLUnsafe) into DOMPurify
- Review whether sanitized shadow root text content is fed into a template engine; add independent escaping/scrubbing there as defense in depth
- If upgrading is not immediately possible, disable SAFE_FOR_TEMPLATES or DOM-returning modes, or post-process shadow root content yourself before template evaluation
Fixed versions
Sources
All live incidents on Threat Watch