Monitor vulnerabilities like this one.
Sign up free to get alerted when software you use is affected.
5.3
DOMPurify: Forbidden tags can be added due to unexpected behavior
GHSA-39q2-94rc-95cp
Summary
DOMPurify, a library used to sanitize user input in web applications, has a bug that allows certain tags to be added to the output even if they are supposed to be forbidden. This can happen when both the 'ADD_TAGS' and 'FORBID_TAGS' features are used together. To fix this issue, update to a newer version of DOMPurify or apply the suggested patch to ensure forbidden tags are properly blocked.
What to do
- Update cure53 dompurify to version 3.4.0.
Affected software
| Ecosystem | Vendor | Product | Affected versions |
|---|---|---|---|
| npm | cure53 | dompurify |
<= 3.3.3 Fix: upgrade to 3.4.0
|
Original title
DOMPurify's ADD_TAGS function form bypasses FORBID_TAGS due to short-circuit evaluation
Original description
## Summary
In `src/purify.ts:1117-1123`, `ADD_TAGS` as a function (via `EXTRA_ELEMENT_HANDLING.tagCheck`) bypasses `FORBID_TAGS` due to short-circuit evaluation.
The condition:
```
!(tagCheck(tagName)) && (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName])
```
When `tagCheck(tagName)` returns `true`, the entire condition is `false` and the element is kept — `FORBID_TAGS[tagName]` is never evaluated.
## Inconsistency
This contradicts the attribute-side pattern at line 1214 where `FORBID_ATTR` explicitly wins first:
```
if (FORBID_ATTR[lcName]) { continue; }
```
For tags, FORBID should also take precedence over ADD.
## Impact
Applications using both `ADD_TAGS` as a function and `FORBID_TAGS` simultaneously get unexpected behavior — forbidden tags are allowed through. Config-dependent but a genuine logic inconsistency.
## Suggested Fix
Check `FORBID_TAGS` before `tagCheck`:
```
if (FORBID_TAGS[tagName]) { /* remove */ }
else if (tagCheck(tagName) || ALLOWED_TAGS[tagName]) { /* keep */ }
```
## Affected Version
v3.3.3 (commit 883ac15)
In `src/purify.ts:1117-1123`, `ADD_TAGS` as a function (via `EXTRA_ELEMENT_HANDLING.tagCheck`) bypasses `FORBID_TAGS` due to short-circuit evaluation.
The condition:
```
!(tagCheck(tagName)) && (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName])
```
When `tagCheck(tagName)` returns `true`, the entire condition is `false` and the element is kept — `FORBID_TAGS[tagName]` is never evaluated.
## Inconsistency
This contradicts the attribute-side pattern at line 1214 where `FORBID_ATTR` explicitly wins first:
```
if (FORBID_ATTR[lcName]) { continue; }
```
For tags, FORBID should also take precedence over ADD.
## Impact
Applications using both `ADD_TAGS` as a function and `FORBID_TAGS` simultaneously get unexpected behavior — forbidden tags are allowed through. Config-dependent but a genuine logic inconsistency.
## Suggested Fix
Check `FORBID_TAGS` before `tagCheck`:
```
if (FORBID_TAGS[tagName]) { /* remove */ }
else if (tagCheck(tagName) || ALLOWED_TAGS[tagName]) { /* keep */ }
```
## Affected Version
v3.3.3 (commit 883ac15)
ghsa CVSS4.0
5.3
Vulnerability type
CWE-783
Published: 16 Apr 2026 · Updated: 16 Apr 2026 · First seen: 16 Apr 2026