Tools / News / Two Flaws in jsPDF, Used by 1.5 Million Developers Weekly, Allow PDF Injection and Critical XSS
Press

Two Flaws in jsPDF, Used by 1.5 Million Developers Weekly, Allow PDF Injection and Critical XSS

· VaultTools

CVE-2026-25755 and CVE-2026-31938 expose a fundamental risk in JavaScript-based browser PDF generation: unsanitized user input flows directly into PDF streams. Patched in jsPDF 4.2.0 and 4.2.1.

VaultTools · March 24, 2026

Programming code displayed on a monitor in orange and blue tones, representing a software vulnerability in a widely used JavaScript library. Photo by Ilya Pavlov on Unsplash

Table of Contents


What Happened

On February 24, 2026, security researchers disclosed CVE-2026-25755, a high-severity vulnerability (CVSS 8.8) in jsPDF, the most widely used JavaScript library for generating PDFs inside a browser. jsPDF sees approximately 1.5 million npm downloads per week and is embedded in thousands of web applications, document editors, and file export tools.

A second vulnerability, CVE-2026-31938 (CVSS 9.6, critical), was published on March 18, 2026, affecting the same library through a different code path. Both flaws were patched: CVE-2026-25755 in jsPDF 4.2.0, CVE-2026-31938 in jsPDF 4.2.1.

What the Vulnerabilities Allow

CVE-2026-25755 lives in the addJS method inside javascript.js. The method concatenates user-controlled input directly into a PDF stream without sanitizing parentheses, which are string delimiters in the PDF specification. An attacker who controls the input can close the /JS string early and inject arbitrary PDF objects or JavaScript actions into the generated document. Any user who opens the resulting PDF is exposed.

CVE-2026-31938 affects the output() function’s options argument. Insufficient sanitization of user-controlled data allows attackers to inject arbitrary HTML and scripts into the browser context when the victim opens the file. The attack requires user interaction but no elevated privileges.

Together the two flaws mean that a web application using an unpatched version of jsPDF can silently produce documents that execute attacker-controlled code on a reader’s machine.

Why JavaScript PDF Libraries Carry This Risk Structurally

PDF is a complex specification with embedded JavaScript, rich metadata, nested compression layers, and multiple codec types. When a JavaScript library constructs PDF output by assembling strings and streams, every point where user input enters that assembly process is a potential injection site.

JavaScript does not enforce memory safety at the language boundary. String concatenation into structured binary formats such as PDF requires explicit, comprehensive sanitization of every control character the format recognizes. Missing even one delimiter class, as happened with the unescaped parenthesis in jsPDF’s addJS, is sufficient for exploitation.

This is not a one-off implementation mistake. It is a consequence of building PDF generation on top of a dynamically typed language with no native representation of structured binary formats. The attack surface grows with the library’s feature count.

How Rust-Based Browser Processing Is Different

Rust enforces memory safety and type correctness at compile time. A Rust-based PDF library compiled to WebAssembly handles file bytes as typed structures, not as strings being assembled through concatenation. There is no equivalent of an unescaped parenthesis creating an injection path because the library never constructs PDF streams through string interpolation of user input.

Beyond the language difference, a Wasm-compiled Rust tool runs in the browser’s sandboxed environment with no server component. Even if a theoretical output flaw existed, there is no server-side session, no remote file store, and no authenticated account for malicious output to pivot into. The blast radius is bounded by the sandbox.

The jsPDF vulnerabilities are a reminder that “browser-based” does not automatically mean “safe.” The implementation language, dependency chain, and architecture all shape the real risk profile.

What Developers Should Do Now

Any application using jsPDF should upgrade to version 4.2.1 or later immediately. Both CVEs are patched in that release.

Developers generating PDFs from user-controlled input should audit every code path where user data reaches PDF stream construction, regardless of library. Input sanitization for PDF is distinct from HTML or SQL sanitization; the relevant characters and structures differ.

For users of web-based document tools generally, the jsPDF incident reinforces a practical question: does the tool generating or processing your document have a published security advisory history? A library embedded in an online document editor or export function carries the same risks whether the user sees it or not.


Sources