The npm prismjs package has accumulated three notable security advisories — a ReDoS class in several language grammars, an XSS in the Command Line plugin, and a DOM clobbering flaw fixed only in version 1.30.0 — and most projects are running it far behind that. PrismJS is one of those libraries that gets embedded once, wrapped by something like react-syntax-highlighter, and then forgotten for five years. Because it runs in the browser and touches strings that often originate from users (comments, README rendering, paste-a-snippet features), its bugs land squarely in XSS and denial-of-service territory. Here is what has actually been disclosed, and how to configure highlighting so the next advisory is a version bump instead of an incident.
The advisory history in order
Three CVEs are worth knowing, all verified against the GitHub Advisory Database:
CVE-2021-32723 — ReDoS in language grammars. Certain grammars (the advisory calls out prism-asciidoc, prism-rest, prism-tap, and prism-eiffel for versions before 1.23.0, with additional languages addressed through 1.24.0) contained regular expressions with catastrophic backtracking. Highlighting attacker-crafted text could hang the browser tab — or the server, if you highlight during SSR. Fixed in Prism v1.24.
CVE-2022-23647 — XSS in the Command Line plugin. The plugin did not properly escape its output, so input text was inserted into the DOM as HTML. Only sites using the Command Line plugin were affected; server-side rendering of Prism was not. Fixed in v1.27.0.
CVE-2024-53382 — DOM clobbering leading to XSS. All versions through 1.29.0 resolved document.currentScript in a way an attacker could shadow with injected HTML such as an img element carrying name="currentScript". Untrusted input containing HTML — but no script at all — could leverage this into script execution. The patch adds a tagName === 'SCRIPT' check, and the fix shipped in version 1.30.0, rated CVSS 4.9.
The pattern across all three: none of them require Prism to be "misused" in an exotic way. They trigger through the ordinary act of highlighting text that an attacker influenced, or loading Prism onto a page where an attacker can inject inert HTML.
Why the DOM clobbering bug matters more than its CVSS score
DOM clobbering is easy to underestimate. The attacker never injects JavaScript — sanitizers that strip script tags and event handlers pass the payload through happily. Instead, an element like an image named currentScript overrides what the library believes about its own environment, redirecting logic that trusts document.currentScript (for example, to derive a base path for loading additional resources).
That means CVE-2024-53382 composes badly with a very common architecture: a site that sanitizes user HTML with a default-configured sanitizer, renders it, and also loads Prism globally for code blocks. Each piece looks fine in isolation. Together, the sanitized-but-attacker-shaped HTML sits in the same document as a library that can be steered by it. If that describes your app, the upgrade to 1.30.0 is not optional housekeeping. For background on the broader bug class, see our guide to cross-site scripting prevention.
Check what you are actually running
Very few projects depend on prismjs directly. It arrives via wrappers, and wrappers pin old versions. react-syntax-highlighter tracked a vulnerable Prism long enough after the DOM clobbering disclosure that users opened issues asking for the bump, and swagger-ui had the same conversation. So audit the real installed version, not the wrapper's:
npm ls prismjs
npm audit --audit-level=moderate
If a wrapper holds you below 1.30.0, force the resolution while you wait for upstream:
{
"overrides": {
"prismjs": "^1.30.0"
}
}
Then re-run your build and smoke-test highlighting — Prism's plugin ecosystem occasionally depends on internals, and a forced bump deserves a render check before it ships.
Hardening rules for any highlighter
Version currency fixes yesterday's CVEs. Configuration decides how much tomorrow's costs you.
Treat highlighting input as untrusted, always. The mental model "it's just a code snippet" is how ReDoS and grammar bugs become reachable. If users can paste, comment, or upload the text you highlight, it is attacker input.
Sanitize after highlighting, not before. Prism outputs HTML markup (spans with token classes). If the surrounding content is user-controlled, run the final composed HTML through DOMPurify before insertion. Sanitizing only the input lets the highlighter itself reintroduce markup.
Cap input size and highlight asynchronously. A byte limit (say, 50 KB per block) plus Web Worker or requestIdleCallback execution converts a catastrophic-backtracking regex from a page-freezing bug into a bounded annoyance. On the server, wrap SSR highlighting in a timeout.
Load only the grammars and plugins you need. CVE-2022-23647 only affected Command Line plugin users; CVE-2021-32723 lived in specific language grammars. Every grammar and plugin you skip is advisory surface you do not carry. Prism's modular build makes this easy — import prismjs/components/prism-python explicitly instead of shipping the kitchen sink.
Set a Content Security Policy. A solid CSP without unsafe-inline script sources is the backstop that turns a successful highlighter XSS into a blocked request.
Maintenance status and what it means for you
Prism 1.x moves slowly. The 1.30.0 release arrived in early 2025 carrying the DOM clobbering fix, roughly three years after 1.29.0's era, while the long-planned rewrite has not shipped as a stable replacement. Slow-moving is not abandoned — the maintainers did respond to a disclosed vulnerability with a patched release — but it does mean you should not expect rapid fixes for lower-severity reports, and you should keep an eye on alternatives (Shiki for build-time highlighting, highlight.js as the long-standing runtime peer) if your risk tolerance is tight.
This is also a case study in why transitive pinning is the real exposure: the bug was fixed upstream, and the ecosystem stayed vulnerable through wrapper lockfiles for months. Dependency scanning that resolves actual installed versions — the way an SCA platform like Safeguard walks lockfiles rather than manifest ranges — is what surfaces the gap between "Prism fixed it" and "my bundle ships it."
FAQ
Which prismjs version fixes all known CVEs?
Version 1.30.0 or later. It contains the DOM clobbering fix (CVE-2024-53382); the Command Line plugin XSS (CVE-2022-23647) was fixed in 1.27.0 and the ReDoS advisories (CVE-2021-32723) in the 1.23–1.24 range.
Is prismjs safe for highlighting user-submitted code?
Yes, with hardening: run 1.30.0+, cap input length, load only needed grammars, sanitize the final HTML with DOMPurify, and serve a CSP without inline script. Highlighting untrusted text on an old version, with plugins you never audited, is where the incidents come from.
My version is pinned by react-syntax-highlighter — what do I do?
Add an npm overrides (or Yarn resolutions) entry forcing prismjs to ^1.30.0, verify rendering still works, and track the wrapper's issue for a proper release. The wrapper's pin does not have to be your pin.
Does server-side rendering avoid these vulnerabilities?
It avoids the DOM-dependent ones — the Command Line plugin XSS advisory explicitly notes server-side usage is not impacted, and DOM clobbering needs a DOM. ReDoS is the opposite: on the server it ties up your event loop instead of one visitor's tab, so input caps and timeouts matter more there, not less.