Safeguard
Open Source

Is the DOMPurify npm Package Safe? CVEs and Secure Usage

DOMPurify (npm) is the right tool for sanitizing HTML against XSS, and it is safe when you keep it patched - but it has had real bypass CVEs, so version discipline matters.

Priya Mehta
Security Analyst
5 min read

The DOMPurify npm package is a well-maintained, widely trusted HTML sanitizer and it is safe to rely on for XSS defense — provided you stay on a current version, because DOMPurify has had genuine sanitizer-bypass CVEs that were fixed in specific releases. Maintained by the security firm cure53, DOMPurify cleans untrusted HTML so you can insert it into the DOM without executing attacker script. That is a high-stakes job, and the honest answer to "is npm dompurify safe?" is: yes, if you patch it like the security-critical dependency it is. This review covers the real vulnerabilities and how to use it well.

What DOMPurify does and why it is hard

DOMPurify takes an untrusted HTML string and returns a sanitized one, stripping scripts, dangerous attributes, and other XSS vectors while preserving safe markup. You reach for it whenever you must render HTML you did not author — user comments, rich-text fields, third-party content.

The reason bypasses keep appearing is that browsers parse HTML in surprisingly forgiving and mutation-prone ways. mutation XSS (mXSS) exploits the gap between how a sanitizer reads markup and how the browser re-parses it after insertion. DOMPurify has to model those parser quirks precisely, and every so often researchers find markup that DOMPurify passes as clean but the browser later mutates into executing script. That is not a sign the library is bad; it is why a maintained, quickly patched sanitizer beats hand-rolled filtering every time.

Real, verified DOMPurify CVEs

These are documented advisories with published fix versions. Treat them as the reason to keep current, not as one-time to-dos:

  • CVE-2024-45801. An XSS bypass that abused nested markup together with prototype pollution to defeat sanitization. Fixed in DOMPurify 2.5.4 (for the 2.x line) and 3.1.3 (for the 3.x line).
  • CVE-2025-26791. A mutation XSS issue that applied when SAFE_FOR_TEMPLATES was enabled. The template-literal detection regex was too loose, so a payload omitting a closing brace could survive sanitization. It carries a CVSS v3.1 base score of 4.5 (medium) and is fixed in DOMPurify 3.2.4.

The pattern is clear: fixes land in point releases, and staying a few versions behind can leave you exposed to a public, documented bypass. If you are on the 2.x branch, understand that the 3.x line receives the most active fixes; migrating to a current 3.x release is the more durable position.

Use the latest, and pin deliberately

The single most important control for npm dompurify is version freshness. Because this is your XSS boundary, treat a DOMPurify upgrade as routine and high priority:

npm install dompurify@latest
npm ls dompurify   # confirm no old duplicate resolved transitively

Watch for transitive copies. A rich-text editor or markdown renderer in your tree may bundle its own DOMPurify at a pinned older version, and that copy is exactly as exploitable as a direct one. npm ls dompurify shows every resolved version; deduplicate so you are not patching the top-level package while an outdated bundled one still runs. Automated software composition analysis will catch a transitively introduced, vulnerable DOMPurify that a manual glance at package.json misses.

Configure it conservatively

DOMPurify is safe by default, and most projects should keep it that way. The risky moves are loosening the config:

import DOMPurify from 'dompurify'

// Safe default
const clean = DOMPurify.sanitize(userHtml)

// Be deliberate about any allowlist widening
const cleanWithLinks = DOMPurify.sanitize(userHtml, {
  ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'p', 'ul', 'ol', 'li'],
  ALLOWED_ATTR: ['href']
})

A few rules. Do not add script, iframe, or event-handler attributes to your allowlist. Be cautious with flags like SAFE_FOR_TEMPLATES — as CVE-2025-26791 shows, some options have their own bypass history, so only enable one if you genuinely need it and are on a version that fixed the associated issue. And never re-introduce raw HTML around DOMPurify's output; sanitize the final string that hits the DOM, not an intermediate one you then modify.

Server-side rendering and jsdom

DOMPurify needs a DOM. In the browser it uses the real one; on the server (SSR, Node APIs) you pair it with jsdom:

import { JSDOM } from 'jsdom'
import createDOMPurify from 'dompurify'

const window = new JSDOM('').window
const DOMPurify = createDOMPurify(window)
const clean = DOMPurify.sanitize(untrustedHtml)

When you run it this way, jsdom becomes part of your XSS boundary too — keep it patched alongside DOMPurify, and make sure the parser it uses matches your assumptions. Sanitizing on the server and again reflecting HTML through a differently configured client path is a common way to open a gap, so keep the configuration consistent across environments.

FAQ

Is the DOMPurify npm package safe to use?

Yes. DOMPurify is maintained by cure53 and is the standard, trusted way to sanitize untrusted HTML against XSS. It is safe when kept current. It has had real bypass CVEs fixed in specific releases, so the practical requirement is patching promptly, not avoiding the library.

Which DOMPurify version should I use?

Use the latest release. For reference, CVE-2024-45801 was fixed in 2.5.4 and 3.1.3, and CVE-2025-26791 was fixed in 3.2.4. The 3.x line receives the most active fixes, so migrate off 2.x and track new releases rather than pinning an old version indefinitely.

Can DOMPurify be bypassed?

It has been, through mutation XSS and specific configuration flags, which is why documented CVEs exist. Each was patched in a point release. Staying current, keeping the default conservative config, and avoiding risky options you do not need keeps your exposure minimal.

Do I need to worry about transitive copies of DOMPurify?

Yes. Editors and renderers often bundle their own DOMPurify at a pinned, possibly outdated version. Run npm ls dompurify to find every resolved copy, deduplicate, and use dependency scanning so an outdated bundled version does not quietly remain your weakest link.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.