CVE-2026-65902
Medium · 6.1CVSS
6.1
EPSS
0.4%
Published
Jul 23, 2026
CISA due date
—
Cloudanix analysis
A website using an older HTML-cleaning library could accidentally let unsafe user content remain on pages and run in other users’ browsers.
- Exploitation
- Requires User Interaction
- Attacker needs
- User Interaction
- Complexity
- Low
- Impact
- Data Tampering
- Component
- Library
- Class
- XSS
- Remediation
- Upgrade
- Effort
- Medium
- Patch risk
- Low
What it actually does
DOMPurify versions before 3.4.7 can allow persistent sanitizer policy poisoning when sanitization is performed without explicit ALLOWED_TAGS or ALLOWED_ATTR configuration and application code uses uponSanitizeElement or uponSanitizeAttribute hooks that mutate data.allowedTags or data.allowedAttributes. Because DOMPurify passes direct references to module-level default allow-list sets into those hooks, a mutation can permanently expand the default allowed tags or attributes for the lifetime of the DOMPurify instance. Subsequent sanitize calls using the default configuration may then allow attacker-controlled HTML elements or attributes that should have been stripped, creating a stored or reflected cross-site scripting condition depending on how sanitized content is later rendered.
Why it matters to the business
Applications that rely on DOMPurify to safely render user-supplied HTML may unintentionally allow malicious content to run in users’ browsers. Successful exploitation can lead to session theft, unauthorized actions performed as the victim, phishing inside a trusted application, data exposure from the browser context, and integrity loss for rendered content. The current public exploitation signal is low: it is not listed in CISA KEV, is not associated with ransomware use, has low EPSS, and no mature exploit is indicated; however, DOMPurify is widely embedded in web applications and downstream frameworks, so affected code paths can be broadly distributed and difficult to inventory.
How an attack unfolds
An attacker first needs an application that uses a vulnerable DOMPurify version and registers an uponSanitizeElement or uponSanitizeAttribute hook that mutates the allowedTags or allowedAttributes object provided to the hook. The attacker then triggers sanitization of crafted content that causes the hook to add a dangerous or application-sensitive tag or attribute to the shared default allow-list. Because the mutation affects the DOMPurify instance’s module-level defaults, removing hooks, clearing configuration, or later using default sanitize calls does not restore the original policy. The attacker then submits a second HTML payload that uses the newly allowed tag or attribute. When the application sanitizes this second payload without explicitly supplying fresh ALLOWED_TAGS or ALLOWED_ATTR arrays, the malicious markup survives and is rendered to a victim. If the payload executes in the browser, the attacker can steal data accessible to page scripts, perform actions as the victim, or redirect the user to malicious content.
How to fix it
Upgrade DOMPurify to version 3.4.7 or later wherever it is used, including direct dependencies, bundled frontend assets, vendored copies, and transitive packages that ship their own DOMPurify build. Rebuild and redeploy frontend bundles after updating package manifests and lockfiles. As a defense-in-depth measure, avoid mutating data.allowedTags and data.allowedAttributes inside DOMPurify hooks; treat hook data as read-only unless the installed version is fixed and the behavior is explicitly intended. Where possible, pass explicit, immutable ALLOWED_TAGS and ALLOWED_ATTR arrays for security-sensitive sanitization calls rather than relying on process-wide defaults. If immediate upgrade is not possible, construct a new DOMPurify instance after any hook activity that may have modified allow-lists, remove risky hooks, and enforce a restrictive Content Security Policy to reduce the impact of any surviving script payloads.
How to confirm the fix worked
Confirm that all deployed package manifests, lockfiles, software composition analysis results, and generated frontend bundles resolve DOMPurify to 3.4.7 or later. Search source code for DOMPurify.addHook usages, especially uponSanitizeElement and uponSanitizeAttribute, and verify that hook implementations do not call add, push, set, assign, or direct property writes against data.allowedTags or data.allowedAttributes. Create a regression test that registers representative hooks, performs a sanitize call, then verifies that a later default-config sanitize call does not allow tags or attributes added during the earlier hook invocation. Validate runtime behavior by submitting benign test markup containing tags or attributes that should be disallowed and confirming they are stripped after upgrade.
Typical attack path
- Identify a web application feature that accepts and later renders user-controlled HTML or rich text.
- Confirm or infer that the application uses a vulnerable DOMPurify version before 3.4.7.
- Find a code path where DOMPurify hooks such as uponSanitizeElement or uponSanitizeAttribute mutate data.allowedTags or data.allowedAttributes.
- Submit crafted content that causes the hook to widen the shared default allow-list for the active DOMPurify instance.
- Submit a follow-on payload that uses the newly allowed tag or attribute to preserve malicious markup through sanitization.
- Wait for a victim to view the sanitized content or interact with a page that renders it.
- Execute JavaScript or browser-side actions in the victim’s trusted application context.
How to detect it
Look for both exposure and evidence of attempted exploitation. For exposure, inspect package manifests, lockfiles, SBOM/SCA output, built frontend artifacts, and vendored JavaScript for DOMPurify versions before 3.4.7. Review source repositories for DOMPurify hooks that reference uponSanitizeElement or uponSanitizeAttribute and mutate data.allowedTags or data.allowedAttributes. For possible exploitation, examine application logs and content storage audit trails for submitted HTML containing tags or attributes that should normally be stripped but later appear in rendered output. Review WAF, reverse proxy, and application request logs for repeated two-stage behavior: an initial submission that influences sanitizer behavior followed by later payloads containing unusual HTML attributes or executable markup. Check CSP violation reports, browser telemetry, JavaScript error logs, and endpoint/web analytics for unexpected inline script execution, blocked script loads, suspicious redirects, credential-phishing overlays, or outbound requests to unfamiliar domains originating from pages that render user-generated HTML. Because this flaw does not create a reliable server-side artifact by itself, absence of a fixed IOC does not prove non-exploitation; detection depends heavily on application-level content auditability and browser-side telemetry.
- DOMPurify.addHook
- uponSanitizeElement
- uponSanitizeAttribute
- data.allowedTags.add
- data.allowedAttributes.add
- data.allowedTags.push
- data.allowedAttributes.push
- data.allowedTags[
- data.allowedAttributes[
- node_modules/dompurify/package.json
- "dompurify": "3.4.5"
- "dompurify":"3.4.5"
- "dompurify": "^3.4.5"
- "dompurify": "~3.4.5"
- dompurify@3.4.5
What your security team should do
- Prioritize inventory of all DOMPurify usage across frontend, server-side rendering, CMS, collaboration, documentation, and rich-text features.
- Upgrade DOMPurify to 3.4.7 or later and redeploy all affected application bundles.
- Review DOMPurify hook implementations for mutation of data.allowedTags or data.allowedAttributes and refactor them to use explicit configuration instead of modifying defaults.
- Add automated dependency checks to fail builds that include DOMPurify versions before 3.4.7.
- Add unit and integration tests proving that disallowed tags and attributes remain blocked across repeated sanitize calls on the same DOMPurify instance.
- Enable or tighten Content Security Policy, especially script-src restrictions and reporting, to reduce and detect browser-side exploitation.
- Review recent user-submitted HTML content, CSP reports, and client-side error telemetry for signs of unexpected executable markup or abnormal outbound requests from trusted pages.
The record
DOMPurify before 3.4.7 (affected versions <= 3.4.5) passes direct references to the module-level DEFAULT_ALLOWED_TAGS and DEFAULT_ALLOWED_ATTR sets to the uponSanitizeElement and uponSanitizeAttribute hooks via data.allowedTags / data.allowedAttributes when sanitize is called without an explicit cfg.ALLOWED_TAGS / cfg.ALLOWED_ATTR array. A hook that mutates these fields permanently widens the default allow-lists for the lifetime of the DOMPurify instance, so all subsequent default-config sanitize calls inherit the widened defaults and attacker payloads using the poisoned tag/attribute name survive sanitization. removeAllHooks(), clearConfig(), and passing a fresh cfg do not recover the state; only constructing a new DOMPurify instance does.
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|
Related vulnerabilities
- GHSA-76mc-f452-cxcm DOMPurify: Hook mutation of `data.allowedTags` / `data.allowedAttributes` permanently… CWE-501
- GHSA-hpcv-96wg-7vj8 DOMPurify: Cross-realm IN_PLACE sanitization leaves executable markup intact via… CWE-501
- CVE-2026-33828 Trust boundary violation in Windows Attestation allows an authorized attacker to elevate… CWE-501
- GHSA-f26g-jm89-4g65 gitoxide: CommandForbiddenInModulesConfiguration Bypass in gix_submodule::File::update()… CWE-501
- GHSA-jf56-mccx-5f3f OpenClaw: Authenticated `/hooks/wake` and mapped `wake` payloads are promoted into the… CWE-501
- GHSA-gfmx-pph7-g46x OpenClaw: Lower-trust background runtime output is injected into trusted `System:`… CWE-501
- CVE-2026-24153 NVIDIA Jetson Linux has a vulnerability in initrd, where the nvluks trusted application… CWE-501
- GHSA-ff64-7w26-62rf Claude Code has Sandbox Escape via Persistent Configuration Injection in settings.json CWE-501