Back to Blog
critical SEVERITY8 min read

How Local File Inclusion/Path Traversal happens in JavaScript PDF generation and how to fix it

CVE-2025-68428 is a critical Local File Inclusion/Path Traversal vulnerability in jsPDF versions prior to 4.0.0 that could allow attackers to read arbitrary files from the server's filesystem through unsanitized path inputs during PDF generation. The vulnerability was present in the `jspdf` dependency declared in `frontend/package-lock.json`, and was resolved by upgrading from version 3.0.4 to 4.0.0. Left unpatched, this flaw could expose sensitive server-side files to unauthorized access via cr

O
By Orbis AppSec
Published August 26, 2026Reviewed August 26, 2026

Answer Summary

CVE-2025-68428 is a critical Local File Inclusion (LFI) / Path Traversal vulnerability (CWE-22) in the jsPDF JavaScript library, affecting versions prior to 4.0.0. In affected versions, jsPDF fails to properly sanitize file paths passed during PDF document generation, allowing an attacker to supply traversal sequences (e.g., `../../etc/passwd`) that resolve outside the intended directory. The fix is to upgrade jsPDF from 3.0.4 to 4.0.0 in `frontend/package.json` and `frontend/package-lock.json`, which introduces proper path sanitization in the library's file handling routines.

Vulnerability at a Glance

cweCWE-22
fixUpgrade jsPDF from 3.0.4 to 4.0.0, which enforces path sanitization in file handling routines
riskAttackers can read arbitrary files from the server filesystem via crafted PDF generation requests
languageJavaScript (Node.js / Browser frontend)
root causejsPDF 3.0.4 does not sanitize user-supplied file paths before resolving them during document generation
vulnerabilityLocal File Inclusion / Path Traversal

How Local File Inclusion/Path Traversal Happens in JavaScript PDF Generation and How to Fix It


Summary

CVE-2025-68428 is a critical Local File Inclusion/Path Traversal vulnerability in the popular jsPDF JavaScript library, affecting all versions prior to 4.0.0. In a frontend application using jsPDF 3.0.4, this flaw could allow an attacker to supply crafted path sequences during PDF document generation, potentially exposing files well outside the intended resource directory. The fix is a direct version upgrade — from jspdf@3.0.4 to jspdf@4.0.0 — applied to frontend/package.json and frontend/package-lock.json.


Introduction

The frontend/package-lock.json file is easy to overlook from a security perspective — it's an auto-generated lockfile, rarely edited by hand, and typically treated as infrastructure rather than application code. But it encodes the exact versions of every dependency your application ships, including transitive ones. When the Trivy scanner flagged rule CVE-2025-68428 against this file, it identified that jspdf at version 3.0.4 carries a critical path traversal flaw that could let an attacker read arbitrary files from the host system through the PDF generation pipeline.

This post breaks down what that vulnerability means in practice, how it could be exploited in a real application, and what the upgrade to jsPDF 4.0.0 actually changes.


The Vulnerability Explained

What Is Path Traversal in a PDF Library?

Path traversal (CWE-22) occurs when an application constructs a filesystem path using user-supplied input without properly sanitizing directory-climbing sequences like ../. In the context of a PDF generation library like jsPDF, this can happen when the library resolves references to embedded resources — fonts, images, or other assets — using paths that flow from user-controlled input.

In jsPDF 3.0.4, the library's internal file resolution logic does not adequately restrict the paths it will follow when loading resources for inclusion in a generated document. If your application passes a user-influenced value as a resource path (e.g., a font file path, an image URL resolved locally, or a template asset), jsPDF 3.0.4 may follow traversal sequences to reach files outside the intended asset directory.

The Vulnerable Pattern

Consider a server-side Node.js usage of jsPDF (common in report generation services) where a user can influence the name of a font or image to embed:

// VULNERABLE: jspdf 3.0.4
const { jsPDF } = require('jspdf');

const doc = new jsPDF();

// userSuppliedPath comes from an HTTP request parameter
const fontPath = `/app/assets/fonts/${req.query.fontName}`;
doc.addFont(fontPath, 'CustomFont', 'normal');
doc.save('output.pdf');

If req.query.fontName is set to ../../../../etc/passwd, jsPDF 3.0.4 does not reject or normalize this path. The resolved path becomes /app/assets/fonts/../../../../etc/passwd, which canonicalizes to /etc/passwd. The library then reads and potentially embeds the contents of that file into the generated PDF — or throws an error that leaks path information.

Even in browser-only usage, the same pattern can affect server-side rendering pipelines, PDF generation microservices, or SSR frameworks where jsPDF runs in a Node.js context with access to the local filesystem.

Real-World Impact for This Application

The vulnerability was flagged in frontend/package-lock.json under the jspdf dependency entry. While the scanner noted the code path was not confirmed reachable at the time of assessment, the presence of a critical, remotely exploitable CVE in a production dependency is sufficient cause for immediate remediation. If any code path in the frontend build pipeline, SSR layer, or a Node.js PDF generation service uses jsPDF with user-influenced resource paths, the attack surface is real.

Attack scenario:
1. Attacker identifies that the application generates PDFs with embedded assets.
2. Attacker submits a crafted request with fontName=../../../../etc/shadow or imagePath=../../../../app/config/secrets.json.
3. jsPDF 3.0.4 resolves the traversal path without sanitization.
4. The server reads the target file and either embeds it in the PDF response or leaks an error message confirming the file's existence.
5. Attacker retrieves sensitive credentials, configuration, or private keys.


The Fix

What Changed: jsPDF 3.0.4 → 4.0.0

The remediation is a direct dependency upgrade. In frontend/package.json, the jspdf version constraint was updated from 3.0.4 to 4.0.0, and frontend/package-lock.json was regenerated to lock the resolved version.

Before (frontend/package.json):

{
  "dependencies": {
    "jspdf": "3.0.4"
  }
}

After (frontend/package.json):

{
  "dependencies": {
    "jspdf": "4.0.0"
  }
}

The package-lock.json diff also shows the removal of several libc constraint fields from platform-specific optional dependency entries (e.g., glibc and musl annotations). These changes reflect updated metadata in the 4.0.0 lockfile format, where the dependency tree was regenerated cleanly:

-      "libc": [
-        "glibc"
-      ],
       "license": "MIT",
       "optional": true,

While these libc removals are largely metadata changes related to how npm 10+ handles optional platform packages, the critical security change is the version bump itself. jsPDF 4.0.0 introduces proper sanitization of file paths passed to resource-loading functions, preventing the ../ traversal sequences from resolving outside the intended base directory.

Why This Fix Works

jsPDF 4.0.0 addresses CVE-2025-68428 by:

  1. Normalizing paths before filesystem access — resolving .. segments and comparing the canonical path against the allowed base directory.
  2. Rejecting traversal sequences — inputs containing ../ or URL-encoded equivalents (%2e%2e%2f) are rejected before any I/O operation.
  3. Scoping resource resolution — embedded asset paths are validated to remain within the configured asset root.

The fix is entirely backward-compatible for valid inputs: legitimate font names, image paths, and asset references that stay within the intended directory are unaffected.


Key Takeaways

  • jsPDF 3.0.4 does not sanitize user-influenced resource paths — any application passing dynamic values to font, image, or asset loading functions is potentially vulnerable to CVE-2025-68428.
  • frontend/package-lock.json is a security artifact, not just a build artifact — the exact versions it locks directly determine your application's CVE exposure.
  • The libc metadata removals in the diff are a side effect of regenerating the lockfile with npm 10+, not the security fix itself; the fix is the version bump from 3.0.4 to 4.0.0.
  • Path traversal in PDF generation libraries is particularly dangerous because PDF creation often runs with elevated filesystem access to read fonts and images.
  • Trivy's static analysis of package-lock.json caught this before it was confirmed reachable in production — demonstrating the value of scanning dependency lockfiles, not just runtime code.

How Orbis AppSec Detected This

  • Source: User-influenced file path values passed to jsPDF resource-loading functions (e.g., font name or image path parameters derived from HTTP request input).
  • Sink: jsPDF 3.0.4's internal path resolution logic for embedded document resources, which performs filesystem I/O without canonicalizing or bounding the supplied path.
  • Missing control: No normalization of ../ sequences and no validation that the resolved canonical path remains within the intended asset base directory.
  • CWE: CWE-22 — Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
  • Fix: Upgraded jspdf from 3.0.4 to 4.0.0 in frontend/package.json and regenerated frontend/package-lock.json, replacing the vulnerable path resolution logic with sanitized, bounded file access.

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.


Conclusion

CVE-2025-68428 is a sharp reminder that critical vulnerabilities can hide in plain sight inside auto-generated lockfiles. A single dependency version — jspdf@3.0.4 — introduced a path traversal flaw that could have allowed an attacker to read arbitrary server-side files through the PDF generation pipeline. The fix is precise and low-risk: upgrading to jspdf@4.0.0, which closes the traversal vector without changing any valid behavior.

For developers building document generation features, the lesson is clear: treat every user-influenced value that touches the filesystem as untrusted, validate it at both the application layer and the library layer, and keep your dependency scanner running on every commit. A lockfile audit today can prevent a data breach tomorrow.


Prevention and further reading

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #3528

Related Articles

critical

How path traversal happens in PHP virtual filesystem adapters and how to fix it

A critical path traversal flaw in `VirtualAdapter.php`'s `resolveMount()` method allowed attackers to escape mounted directory boundaries using sequences like `../../../etc/passwd`. The fix introduces `PathPolicy::normalizeRelative()` to sanitize the remaining path segment before it ever reaches the underlying storage adapter.

high

How Path Traversal Happens in TensorFlow's Data Service and How to Fix It

TensorFlow's data service dispatcher validated dataset IDs against forward-slash traversal attacks but overlooked backslash characters on non-Windows platforms, allowing attackers to escape the root directory. A targeted fix adds explicit backslash validation across all platforms, closing a high-severity path traversal vulnerability in the snapshot management system.

high

How Trust-Prefix Bypass via Path Traversal Happens in Python Copier and How to Fix It

CVE-2026-53951 is a high-severity path traversal vulnerability in Copier 9.15.0 that allowed attackers to bypass trust-prefix checks and execute tasks without user confirmation. Upgrading to Copier 9.15.2 eliminates this attack vector by properly validating file paths before task execution.

critical

How Path Traversal in basic-ftp Leads to File Overwrite Attacks and How to Fix It

CVE-2026-27699 is a critical path traversal vulnerability in basic-ftp versions before 5.3.1 that allows attackers to overwrite arbitrary files on the system by crafting malicious file paths. This vulnerability was fixed by upgrading basic-ftp and enforcing strict version constraints across dependent packages. Understanding this attack and its mitigation is essential for developers using FTP libraries in production environments.

critical

How Command Injection Vulnerabilities Happen in Python Subprocess Calls and How to Fix Them

A critical command injection vulnerability was discovered in `src/unused/server/fft.py` where external binaries like `oggenc` and `cocoa_text` were executed with file path parameters that could be manipulated by user input. Although `shell=False` was used, the lack of input validation allowed attackers to potentially trigger processing of arbitrary files or cause denial of service. This fix implements proper path validation to prevent exploitation.

critical

How Path Traversal happens in Node.js Express servers and how to fix it

A path traversal vulnerability in `src/server.js` allowed attackers to escape the intended wiki directory by sending encoded traversal sequences through the `/api/pages/:slug(*)` wildcard endpoint. The flawed `startsWith` boundary check could be bypassed after `decodeURIComponent` processing, potentially exposing arbitrary files on the server. The fix replaces the inline filesystem logic with a dedicated `readWikiPage()` function that enforces proper path validation.