The pdfjs-dist npm package is the prebuilt distribution of Mozilla's PDF.js library, and while it is the de facto standard for rendering PDFs in JavaScript, versions before 4.2.67 contain CVE-2024-4367, a high-severity flaw that lets a malicious PDF execute arbitrary JavaScript in the page that opened it. If your app displays PDFs supplied by users, checking your pdfjs-dist version is not optional. This review covers the vulnerability, the fix, and how to render untrusted documents safely.
PDF.js powers the PDF viewer built into Firefox and is embedded in countless web apps through the npm pdfjs-dist package. That ubiquity is exactly why a code-execution bug in it is serious: the same library sits behind an enormous number of "view attachment" and "preview document" features.
CVE-2024-4367 explained
The vulnerability, disclosed in May 2024 and tracked as CVE-2024-4367, lives in how PDF.js handled font rendering. When processing certain font types, the library used JavaScript eval() on data taken from the PDF file. Because a PDF is attacker-controlled input, a crafted font object could smuggle in JavaScript that then ran in the context of the hosting page.
Two details make this worse than a typical parsing bug. First, eval support was on by default (isEvalSupported: true), so vulnerable behavior was the out-of-the-box behavior. Second, the injected script runs in the origin of the site embedding the viewer, meaning it can read cookies, tokens, and DOM belonging to your application. That is full client-side compromise from the simple act of a user opening a document.
Affected versions are those before 4.2.67. The fix shipped in 4.2.67, which stops routing font data through eval. The advisory to verify directly is GHSA-wgrm-67xf-hhpq.
Check and fix your version
Start by finding what you actually ship. Because many UI component libraries wrap PDF.js, pdfjs npm often arrives transitively:
npm ls pdfjs-dist
If the resolved version is below 4.2.67, upgrade:
npm install pdfjs-dist@latest
If a wrapper library (a react-pdf-style component, for example) pins an old pdfjs-dist, upgrade the wrapper or override the transitive version. In npm you can force the resolved version with an overrides block in package.json:
{
"overrides": {
"pdfjs-dist": ">=4.2.67"
}
}
The transitive case is the one teams miss, since you may never have written pdfjs-dist in your own dependency list. This is where a scan that resolves the full tree earns its keep.
Defense in depth for untrusted PDFs
Upgrading fixes CVE-2024-4367, but if you render documents that users upload, you want more than one layer. A few measures that hold up regardless of any single CVE:
Disable eval explicitly. Even on a patched version, pass isEvalSupported: false when you construct the viewer if you do not need the functionality it enables. Belt and suspenders.
import * as pdfjsLib from "pdfjs-dist";
const loadingTask = pdfjsLib.getDocument({
url: fileUrl,
isEvalSupported: false,
});
Set a strict Content Security Policy. A CSP that forbids inline script and restricts sources sharply limits what injected JavaScript can do, turning a full compromise into a blocked attempt. This is the single most valuable mitigation for any client-side code-execution bug.
Run the worker where it belongs. PDF.js does its parsing in a Web Worker; keep it there rather than disabling the worker, since that isolates the heavy, attacker-facing parsing from your main thread.
Consider rendering server-side or in a sandboxed iframe for high-risk flows. If untrusted PDFs never touch your primary origin, a bug in the parser cannot reach your users' sessions.
Keeping the dependency healthy
The npm pdfjs-dist package is actively maintained by Mozilla, which is good news: fixes ship promptly and the release cadence is steady. The risk is not an abandoned project; it is version drift. A viewer that was current when you built the feature slowly falls behind, and one day a published CVE names your pinned version.
Two habits keep you current. Commit your lockfile and run npm audit in CI so a new advisory against pdfjs-dist surfaces on the next build. And add an SCA tool that resolves transitive dependencies, because the wrapped-component case is precisely where a plain npm ls in a hurry misses the vulnerable copy. A scanner such as Safeguard can flag that a component library pulled in an outdated pdfjs npm build and point you at the minimum safe bump. If you want to compare that approach against alternatives, our Snyk comparison walks through transitive detection.
FAQ
Is pdfjs-dist safe to use?
Yes, on version 4.2.67 or later. It is Mozilla's actively maintained PDF renderer. The concern is specifically versions before 4.2.67, which are vulnerable to CVE-2024-4367 arbitrary JavaScript execution from a malicious PDF.
What is CVE-2024-4367?
A high-severity vulnerability in PDF.js where crafted font data in a PDF could be passed to eval(), executing attacker JavaScript in the hosting page's origin. It was fixed in pdfjs-dist 4.2.67, and can be mitigated by setting isEvalSupported to false.
How do I know if a library I use includes pdfjs-dist?
Run npm ls pdfjs-dist to see the full dependency path. Many PDF-viewer components wrap PDF.js, so it commonly appears as a transitive dependency even if you never added it directly.
Do I still need to disable eval after upgrading?
Upgrading removes the specific bug, but passing isEvalSupported: false and enforcing a strict Content Security Policy are cheap defense-in-depth measures worth keeping, especially when rendering user-supplied PDFs.