Vulnerability AlertJanuary 6, 20269 min read

Critical Path Traversal Vulnerability in jsPDF Library (CVE-2025-68428)

A critical local file inclusion vulnerability in jsPDF allows attackers to read arbitrary files from the server file system through unsanitized path parameters in Node.js environments.

CVE-2025-68428 is a critical path traversal and local file inclusion vulnerability affecting jsPDF, a widely-used JavaScript library for generating PDF documents. The flaw allows attackers to read arbitrary files from the local file system in Node.js environments by exploiting insufficient input validation in multiple file-handling methods. With a CVSS 4.0 score of 9.2 (Critical), this vulnerability poses a significant risk to applications that allow user-controlled file paths to be passed to jsPDF methods.

The vulnerability specifically affects the Node.js builds of jsPDF (versions prior to 4.0.0) and impacts several critical methods including loadFile, addImage, html, and addFont. When exploited, attackers can extract sensitive configuration files, application source code, database credentials, and other confidential data that resides on the server file system. The extracted content is embedded verbatim into generated PDF documents, making exfiltration straightforward.

Understanding CVE-2025-68428

jsPDF is a popular open-source library that enables developers to generate PDF documents directly from JavaScript code, both in browser environments and Node.js applications. It provides methods for adding text, images, fonts, and HTML content to PDFs programmatically, making it a common choice for automated document generation workflows.

The vulnerability stems from inadequate validation of file path parameters in the Node.js-specific implementation of jsPDF. When developers pass user-controlled input to methods that load external files, attackers can inject path traversal sequences to access files outside the intended directory structure.

The affected methods include:

  • loadFile() - Loads file contents for inclusion in PDFs
  • addImage() - Loads and embeds images from the file system
  • html() - Processes HTML files that may reference local resources
  • addFont() - Loads custom font files from disk

How the Vulnerability Works

Path Traversal Attack Mechanism

Path traversal vulnerabilities, also known as directory traversal or dot-dot-slash attacks, occur when applications fail to properly validate file path inputs. Attackers exploit this by using special character sequences like "../" to navigate up the directory tree and access files outside the intended scope.

In the case of CVE-2025-68428, vulnerable jsPDF code accepts file paths as the first argument to multiple methods without sufficient sanitization. An attacker can provide paths like:

// Accessing sensitive system files
"../../../../etc/passwd"
"../../../../etc/shadow"

// Reading application configuration
"../../../../app/config/database.yml"
"../../../../.env"

// Extracting source code
"../../../../app/routes/api.js"
"../../../../package.json"

// Accessing private keys
"../../../../home/user/.ssh/id_rsa"
"../../../../var/secrets/api_keys.txt"

Exploitation Example

Consider a Node.js application that allows users to generate PDF reports with custom images. If the application naively passes user input to jsPDF without validation:

// Vulnerable code example
const jsPDF = require('jspdf');
const express = require('express');
const app = express();

app.post('/generate-pdf', (req, res) => {
  const doc = new jsPDF();
  const imagePath = req.body.imagePath; // User-controlled input
  
  // Vulnerable: No path validation
  doc.addImage(imagePath, 'PNG', 10, 10, 100, 100);
  
  const pdfBuffer = doc.output('arraybuffer');
  res.send(Buffer.from(pdfBuffer));
});

// Attacker sends request with malicious path
// POST /generate-pdf
// { "imagePath": "../../../../etc/passwd" }

// Result: /etc/passwd contents embedded in returned PDF

Node.js-Specific Attack Surface

This vulnerability only affects the Node.js builds of jsPDF (dist/jspdf.node.js and dist/jspdf.node.min.js). Browser-based implementations are not affected because browsers enforce strict security policies that prevent JavaScript from directly accessing the local file system. In Node.js environments, however, the runtime has full file system access, making path traversal attacks viable and dangerous.

Impact and Risk Assessment

Severity Classification

CVE-2025-68428 has been assigned a CVSS 4.0 score of 9.2 (Critical) by GitHub Security Advisory Database. The severity reflects several aggravating factors:

  • Network Attack Vector (AV:N): Exploitable remotely over network connections
  • Low Attack Complexity (AC:L): Simple to exploit without special conditions
  • No Privileges Required (PR:N): No authentication or authorization needed
  • No User Interaction (UI:N): Exploitation requires no user action
  • High Confidentiality Impact (VC:H, SC:H): Complete information disclosure

Real-World Consequences

Successful exploitation of this vulnerability can lead to:

  • Exposure of database credentials stored in configuration files
  • Disclosure of API keys, authentication tokens, and cryptographic secrets
  • Leakage of proprietary source code and intellectual property
  • Access to user data, session information, and private keys
  • Information gathering for follow-up attacks targeting other vulnerabilities

Affected Deployments

Applications at highest risk include document generation services, reporting platforms, invoice and receipt generators, data export systems, and any Node.js application that accepts user input for file paths passed to jsPDF methods. Cloud-hosted Node.js applications and containerized services running vulnerable jsPDF versions are particularly exposed if they handle untrusted input.

Affected Versions and Patches

Vulnerable Versions

All versions of jsPDF prior to 4.0.0 are affected by this vulnerability. This includes:

  • jsPDF 3.x series (all versions)
  • jsPDF 2.x series (all versions)
  • jsPDF 1.x series (all versions)

Patched Version

The vulnerability has been fixed in jsPDF version 4.0.0. This release implements strict file system access controls by default, restricting file operations to explicitly allowed directories. According to the maintainers, this semver-major update does not introduce other breaking changes beyond the security improvements.

The fix includes enhanced path validation, whitelisting of allowed directories, rejection of path traversal sequences, and configurable file system permissions for applications requiring broader file access.

Remediation and Mitigation

Immediate Action: Upgrade to jsPDF 4.0.0

The primary remediation is upgrading to jsPDF version 4.0.0 or later. Update your package.json and install the patched version:

# Update package.json
{
  "dependencies": {
    "jspdf": "^4.0.0"
  }
}

# Install the update
npm install jspdf@latest

# Or with yarn
yarn upgrade jspdf@latest

# Verify installed version
npm list jspdf
# Should output: jspdf@4.0.0 or higher

Node.js Permission Model (Node.js 20+)

For applications running on recent Node.js versions, the maintainers recommend using the experimental permission flag to restrict file system access:

# Start Node.js with file system restrictions
node --permission --allow-fs-read=/app/data --allow-fs-write=/app/output app.js

# The permission model is experimental in Node.js 20.x
# Stable in Node.js 22.13.0, 23.5.0, and 24.0.0+

# Example: Restrict to specific directories only
node --permission \
  --allow-fs-read=/app/public \
  --allow-fs-read=/app/assets \
  --allow-fs-write=/tmp/pdfs \
  server.js

Input Validation and Sanitization

If immediate upgrading is not feasible, implement strict input validation for any user-controlled paths passed to jsPDF methods:

const path = require('path');
const fs = require('fs');

// Secure path validation function
function sanitizeFilePath(userInput, baseDir) {
  // Remove null bytes and normalize
  const cleaned = userInput.replace(/\0/g, '');
  
  // Resolve to absolute path
  const absolutePath = path.resolve(baseDir, cleaned);
  
  // Ensure path stays within base directory
  if (!absolutePath.startsWith(path.resolve(baseDir))) {
    throw new Error('Invalid file path: directory traversal detected');
  }
  
  // Verify file exists and is readable
  if (!fs.existsSync(absolutePath)) {
    throw new Error('File not found');
  }
  
  return absolutePath;
}

// Secure usage example
app.post('/generate-pdf', (req, res) => {
  try {
    const baseDir = '/app/public/images';
    const safePath = sanitizeFilePath(req.body.imagePath, baseDir);
    
    const doc = new jsPDF();
    doc.addImage(safePath, 'PNG', 10, 10, 100, 100);
    res.send(doc.output());
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

Whitelist Approach

Instead of accepting arbitrary paths, use a whitelist of allowed files or map user selections to safe file paths:

// Whitelist mapping approach
const ALLOWED_IMAGES = {
  'logo': '/app/assets/logo.png',
  'header': '/app/assets/header.jpg',
  'footer': '/app/assets/footer.png'
};

app.post('/generate-pdf', (req, res) => {
  const imageKey = req.body.imageSelection;
  
  if (!ALLOWED_IMAGES[imageKey]) {
    return res.status(400).json({ error: 'Invalid image selection' });
  }
  
  const doc = new jsPDF();
  doc.addImage(ALLOWED_IMAGES[imageKey], 'PNG', 10, 10, 100, 100);
  res.send(doc.output());
});

Containerization and Sandboxing

For defense in depth, run Node.js applications in containers with restricted file system mounts, use read-only file systems where possible, apply principle of least privilege for container user permissions, and implement security contexts with AppArmor or SELinux profiles.

Detection and Response

Identifying Vulnerable Dependencies

Use automated tools to scan your dependencies for vulnerable jsPDF versions:

# npm audit
npm audit

# Check for specific CVE
npm audit | grep CVE-2025-68428

# Generate detailed report
npm audit --json > audit-report.json

# Prismor scanning (fastest and most comprehensive)
pip install prismor
prismor scan

# Or scan specific manifest
prismor scan --file package.json

# OWASP Dependency-Check
dependency-check --project myapp --scan ./

Prismor provides comprehensive vulnerability scanning with detailed severity analysis, fixed versions, and direct links to vulnerability databases. It supports all major package managers and can be run locally via CLI or integrated into your CI/CD pipeline. Visit prismor.dev to scan your dependencies for CVE-2025-68428 and other vulnerabilities.

Log Analysis for Exploitation Attempts

Monitor application logs for suspicious file path patterns that may indicate exploitation attempts. Look for path traversal sequences in request parameters, access to sensitive system files, repeated failed file access attempts, and unusual PDF generation patterns. Implement alerting on detected path traversal patterns and anomalous file access behavior.

Conclusion

CVE-2025-68428 represents a serious security vulnerability in a widely-deployed JavaScript library. The combination of critical severity, ease of exploitation, and potential for sensitive data exposure makes this a high-priority issue for any organization using jsPDF in Node.js applications.

The fix in jsPDF 4.0.0 provides robust protection through default-deny file system access policies, addressing the root cause while maintaining backward compatibility for most use cases. Organizations should prioritize upgrading to the patched version and implementing additional defense-in-depth measures such as input validation, containerization, and the Node.js permission model.

This vulnerability underscores the importance of secure coding practices when handling user input, particularly for file system operations. Never trust user-provided file paths without strict validation, always use whitelisting approaches when possible, and implement multiple layers of security controls to minimize the impact of potential vulnerabilities.

For the latest information and updates, refer to the official GitHub Security Advisory at GHSA-f8cm-6447-x5h2 and the NVD entry at CVE-2025-68428.