Apr 3, 2026·6 min read·48 visits
DOMPurify < 3.3.2 skips URI validation for attributes approved via the ADD_ATTR predicate function, allowing DOM-based XSS via malicious protocols.
DOMPurify versions prior to 3.3.2 contain a vulnerability where the ADD_ATTR predicate function short-circuits internal validation logic. This allows dynamically approved attributes to bypass URI-safe sanitization, potentially leading to DOM-based Cross-Site Scripting (XSS) via dangerous protocols like javascript: or data:.
DOMPurify is an HTML, MathML, and SVG sanitization library designed to prevent DOM-based Cross-Site Scripting (XSS) attacks. It relies on a strict allowlist of elements and attributes, rejecting unrecognized or dangerous input. To support custom application requirements, DOMPurify allows developers to extend this allowlist using configurations such as the ADD_ATTR option.
Recent versions of DOMPurify introduced the ability to pass a predicate function to ADD_ATTR, allowing developers to evaluate attributes dynamically. GHSA-CJMM-F4JC-QW8R identifies a logical flaw in how this predicate function integrates with DOMPurify's internal validation pipeline. When the predicate function approves an attribute, the library skips subsequent mandatory safety checks.
This bypass explicitly affects URI validation. Attributes that require URI sanitization, such as href or src, normally undergo strict protocol checking to block javascript:, vbscript:, or data: payloads. Because the predicate function's approval short-circuits this pipeline, applications dynamically allowing these attributes are exposed to XSS attacks.
The vulnerability resides within DOMPurify's internal _isValidAttribute function. This function is responsible for analyzing an attribute's name, its associated tag, and its value to determine if it is safe to include in the sanitized Document Object Model (DOM). The validation process involves multiple distinct phases: allowlist checking, hook execution, and URI protocol verification.
When a developer configures ADD_ATTR as a predicate function, DOMPurify evaluates it via the EXTRA_ELEMENT_HANDLING.attributeCheck routine. In vulnerable versions of the library, if this predicate function returns true, the _isValidAttribute function executes an early return. It immediately yields true to the caller, confirming the attribute as safe.
This early return mechanism fundamentally breaks the sanitization pipeline. The URI protocol verification phase occurs later in the _isValidAttribute execution flow. By exiting early, the library never evaluates the attribute's value against the list of prohibited URI schemes. The library operates under the incorrect assumption that the predicate function has already performed comprehensive validation of both the attribute name and its value.
The flaw stems from a conditional short-circuit in the attribute validation sequence. While the exact patch diff is abstracted in the advisory, the structural logic failure is well-documented. The vulnerable implementation processes the predicate function output and halts further validation upon a positive result.
// Vulnerable internal logic concept
function _isValidAttribute(tag, attrName, attrValue) {
// ... [allowlist checks] ...
// Predicate function evaluation via ADD_ATTR
if (config.ADD_ATTR_FUNCTION && config.ADD_ATTR_FUNCTION(attrName, tag)) {
return true; // EARLY RETURN: Skips all subsequent checks
}
// ... [mandatory URI validation for href, src, etc.] ...
if (isURI(attrName)) {
if (containsDangerousProtocol(attrValue)) {
return false;
}
}
return true;
}The remediation requires modifying this logic to decouple allowlist approval from value validation. The patch ensures that predicate functions only authorize the presence of the attribute, not the safety of its contents. The attribute must still pass through the protocol verification phase.
In the patched version (3.3.2), the _isValidAttribute function registers the attribute as permitted by the allowlist but continues execution. The standard URI checks process the attrValue regardless of how the attribute was authorized.
Exploitation of GHSA-CJMM-F4JC-QW8R requires a specific implementation pattern within the target application. The attacker must target an endpoint where DOMPurify sanitizes input using an ADD_ATTR predicate function. Crucially, this predicate function must authorize an attribute capable of executing code (like href) without manually validating the attribute's value.
A typical vulnerable configuration looks like this:
const cleanHTML = DOMPurify.sanitize(userInput, {
ADD_ATTR: (attrName, tagName) => {
// Vulnerable: Approves the attribute based solely on name and tag
return tagName === 'a' && attrName === 'href';
}
});An attacker crafts a payload utilizing a dangerous protocol. A standard vector is <a href="javascript:alert(document.domain)">Click Me</a>. When DOMPurify processes this input, the ADD_ATTR predicate evaluates tagName === 'a' and attrName === 'href', returning true.
Because of the vulnerability, DOMPurify skips checking the href value for the javascript: protocol. The resulting cleanHTML retains the malicious payload exactly as input. When the victim interacts with the injected element, the JavaScript executes within the security context of the vulnerable application.
The primary impact of this vulnerability is DOM-based Cross-Site Scripting (XSS). Successful exploitation allows an attacker to execute arbitrary JavaScript within the context of the user's session. The severity is constrained only by the requirement for user interaction and the specific DOMPurify configuration employed by the target application.
An attacker achieving XSS can read sensitive data such as session cookies, local storage tokens, and anti-CSRF nonces. They can also perform actions on behalf of the user, modify the Document Object Model to present false information, or exfiltrate sensitive data displayed on the page. The confidentiality and integrity impacts are high for the affected user session.
The CVSS 4.0 vector (CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N) reflects these characteristics. The attack vector is network-based, requires no privileges, but mandates user interaction (UI:P). The impacts to the vulnerable system itself are negligible, but the subsequent system (the user's browser environment) suffers low to moderate confidentiality and integrity degradation.
The definitive mitigation for this vulnerability is upgrading the dompurify package to version 3.3.2 or later. The maintainers (Cure53) have corrected the internal validation logic to ensure that attributes approved via predicate functions still undergo standard URI protocol sanitization. Developers should update their dependency manifests and rebuild their applications.
For environments where immediate upgrading is not feasible, developers must implement manual validation within their ADD_ATTR predicate functions. The predicate must inspect the attribute value and reject dangerous protocols explicitly.
// Interim mitigation strategy
ADD_ATTR: (attrName, tagName, attrValue) => {
if (tagName === 'a' && attrName === 'href') {
// Manually block dangerous protocols
const normalizedValue = attrValue.trim().toLowerCase();
if (normalizedValue.startsWith('javascript:') ||
normalizedValue.startsWith('data:') ||
normalizedValue.startsWith('vbscript:')) {
return false;
}
return true;
}
return false;
}> [!NOTE] > Relying on manual protocol validation is error-prone. The regex and parsing rules for identifying dangerous protocols in HTML are complex. The provided interim code is a baseline defense; upgrading the library is the only comprehensive solution.
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
dompurify Cure53 | < 3.3.2 | 3.3.2 |
| Attribute | Detail |
|---|---|
| CWE | CWE-79 (Improper Neutralization of Input During Web Page Generation) |
| Attack Vector | Network |
| CVSS Score | 5.3 (Medium) |
| Impact | High Confidentiality, High Integrity (Session context) |
| Exploit Status | Proof of Concept (PoC) available |
| User Interaction | Required |
CVE-2026-59944 is a path traversal and link-following vulnerability in Composer, the PHP dependency manager. This flaw allows malicious or compromised packages to bypass previous path-hardening protections and perform arbitrary filesystem operations outside of their designated installation directory, leading to unauthorized permission modifications or execution proxy creations.
A critical Broken Object Level Authorization (BOLA) vulnerability was identified in Trigger.dev before version v4.5.2. An authenticated attacker could trigger a run replay and supply an arbitrary target environmentId belonging to a completely different tenant. Because the server failed to validate whether the target environment belonged to the same project or organization as the source run, it would execute the task within the victim's environment, resulting in unauthorized cross-tenant write operations and remote task execution.
A critical Server-Side Request Forgery (SSRF) vulnerability in Trigger.dev prior to version 4.5.2 allows authenticated organization members to configure webhook alert channels with unvalidated target URLs. This can lead to internal network scanning and cloud metadata extraction.
A Server-Side Request Forgery (SSRF) vulnerability exists in the rmcp OAuth client, which is part of the Model Context Protocol (MCP) Rust SDK. The vulnerability arises from insecure processing of the resource_metadata parameter in WWW-Authenticate headers returned by a malicious or compromised MCP server. The client parses and fetches absolute URLs from this header without validation of scheme, origin, or network routing, allowing remote attackers to initiate HTTP GET requests to local network interfaces, RFC 1918 private subnets, or cloud metadata endpoints.
A module allowlist bypass vulnerability (CVE-2026-92945 / GHSA-7q3f-wx44-378m) was identified in the vm2 sandboxing library prior to version 3.11.7. This flaw permits unauthenticated or untrusted code running within the sandbox environment to bypass explicit module restrictions. When the transitive resolution option is disabled, the system fails to validate file system path boundaries, allowing prefix-sharing sibling directories to be resolved and loaded, thereby escaping intended sandbox restrictions.
CVE-2026-92941 is a critical sandbox-escape and trust-manipulation vulnerability in the vm2 library (versions 3.11.3 to 3.11.6). This security flaw allows untrusted code executing within a NodeVM sandbox environment to compromise the global TLS trust store of the host Node.js process. By leveraging a design flaw where the host's native 'tls.setDefaultCACertificates' can be executed via a proxy wrapper, combined with a bridge unwrapping bypass in the 'url' module, an attacker can modify the process-wide default root Certificate Authorities. Consequently, all subsequent outbound TLS/HTTPS clients running on the host thread are forced to trust attacker-signed certificates, facilitating transparent Man-in-the-Middle (MitM) attacks. The vulnerability was resolved in version 3.11.7 of vm2 by introducing built-in member-level sanitization before applying read-only proxy wrappers.