Listen to this Post
Intro (how CVE-2026-41239 works):
When DOMPurify is used with `SAFE_FOR_TEMPLATES: true` (which is meant to strip ${...}, {{...}}, and `<%...%>` expressions) and simultaneously with a DOM‑returning mode like RETURN_DOM: true, `RETURN_DOM_FRAGMENT: true` or IN_PLACE: true, an attacker can inject template expressions that survive the sanitization pass inside `` element content.
The vulnerability arises because DOMPurify uses two mechanisms to strip template expressions:
1. Per‑node scrubbing (_sanitizeElements) – it walks each text node individually.
2. Final normalization pass (_scrubTemplateExpressions) – it calls `node.normalize()` to merge adjacent text nodes and then walks the merged nodes, stripping any expressions that only appear after merging.
The gap is in the final pass: `_scrubTemplateExpressions` uses a standard `NodeIterator` rooted at the output body. According to the DOM specification, a `NodeIterator` does not descend into <template>.content. The template element’s content lives in a separate `DocumentFragment` outside the normal child‑node tree. For the same reason, `node.normalize()` also does not normalize text nodes inside <template>.content. Consequently, the final scrub pass never runs on `` content.
To exploit this, an attacker splits a malicious expression (e.g., ${alert(1)}) across two adjacent custom elements inside a <template>. When DOMPurify removes the disallowed elements (with KEEP_CONTENT: true, the default), it extracts the text children and places them as two separate text nodes inside the template’s content fragment. Each fragment alone does not match any template‑expression regex, so DOMPurify leaves them untouched. Only when a downstream template engine calls `normalize()` on the template content (a common practice in component‑based frameworks) do the fragments merge into a full template expression, which is then evaluated – leading to XSS.
DailyCVE Form:
Platform: DOMPurify library Version: 1.0.10 – 3.3.x Vulnerability: template‑expression bypass Severity: Medium (CVSS 6.8) Date: 2026‑04‑23 Prediction: patch expected 2026‑04‑14 (3.4.0)
What Undercode Say (Analytics):
To verify the presence of this vulnerability in your environment, you can run the following bash commands or JavaScript test snippets.
Check DOMPurify version npm list dompurify | grep dompurify If version is between 1.0.10 and 3.3.x, you are vulnerable.
// Quick test – execute in browser console
const dirty = '<template><x-split-1>$</x-split-1><x-split-2>{alert("XSS")}</x-split-2></template>';
const sanitized = DOMPurify.sanitize(dirty, { RETURN_DOM: true, SAFE_FOR_TEMPLATES: true });
const tmpl = sanitized.querySelector('template');
tmpl.content.normalize();
console.log(tmpl.content.textContent); // Should print "$ {alert("XSS")}" -> "${alert("XSS")}"
Exploit:
The attacker crafts HTML like:
<template>
<x-split-1>$</x-split-1>
<x-split-2>{alert(document.cookie)}</x-split-2>
</template>
When the application passes this through DOMPurify with `SAFE_FOR_TEMPLATES` and RETURN_DOM, the individual fragments survive. Later, when the application calls `normalize()` on the template’s content and evaluates it (e.g., via new Function), the full expression executes – exfiltrating cookies or performing other malicious actions.
Protection from this CVE:
- Upgrade to DOMPurify version 3.4.0 or later.
- If upgrading is not immediately possible, avoid using
RETURN_DOM,RETURN_DOM_FRAGMENT, or `IN_PLACE` together withSAFE_FOR_TEMPLATES. - Alternatively, use the default string‑output mode (which is not vulnerable) and only then convert the sanitized string to DOM nodes.
- Disable template‑expression evaluation in your downstream template engine for any content that originated from user input.
Impact:
- Affected applications: those that use DOMPurify with `SAFE_FOR_TEMPLATES: true` in combination with any DOM‑returning mode, and whose downstream template engine processes `` element content.
- Attacker capability: inject arbitrary template expressions (
${...},{{...}},<%...%>) into the sanitized DOM output inside `` elements. - Consequences: if the consuming template engine evaluates these expressions, it leads to template injection, which in client‑side contexts causes Cross‑Site Scripting (XSS), potentially allowing session hijacking, data theft, or full account compromise.
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

