CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-CJMM-F4JC-QW8R
5.3

GHSA-CJMM-F4JC-QW8R: DOM-based XSS Bypass in DOMPurify via ADD_ATTR Predicate

Amit Schendel
Amit Schendel
Senior Security Researcher

Apr 3, 2026·6 min read·1 visit

PoC Available

Executive Summary (TL;DR)

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:.

Vulnerability Overview

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.

Root Cause Analysis

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.

Code Analysis

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

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.

Impact Assessment

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.

Remediation

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.

Technical Appendix

CVSS Score
5.3/ 10
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

Affected Systems

dompurify (npm package)

Affected Versions Detail

Product
Affected Versions
Fixed Version
dompurify
Cure53
< 3.3.23.3.2
AttributeDetail
CWECWE-79 (Improper Neutralization of Input During Web Page Generation)
Attack VectorNetwork
CVSS Score5.3 (Medium)
ImpactHigh Confidentiality, High Integrity (Session context)
Exploit StatusProof of Concept (PoC) available
User InteractionRequired

MITRE ATT&CK Mapping

T1059.007JavaScript
Execution
T1189Drive-by Compromise
Initial Access
T1539Steal Web Session Cookie
Credential Access
CWE-79
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

Vulnerability Timeline

Security advisory published (GHSA-cjmm-f4jc-qw8r).
2026-04-03
DOMPurify version 3.3.2 released with the fix.
2026-04-03
Vulnerability details added to OSV and major vulnerability databases.
2026-04-03

References & Sources

  • [1]Official Advisory
  • [2]GitHub Release
  • [3]OSV Record
  • [4]Vulnerability Database (CIRCL)
  • [5]Aliyun AVD