VYPR
High severityNVD Advisory· Published Mar 18, 2025· Updated Mar 18, 2025

jsPDF Bypass Regular Expression Denial of Service (ReDoS)

CVE-2025-29907

Description

jsPDF is a library to generate PDFs in JavaScript. Prior to 3.0.1, user control of the first argument of the addImage method results in CPU utilization and denial of service. If given the possibility to pass unsanitised image urls to the addImage method, a user can provide a harmful data-url that results in high CPU utilization and denial of service. Other affected methods are html and addSvgAsImage. The vulnerability was fixed in jsPDF 3.0.1.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
jspdfnpm
< 3.0.13.0.1

Affected products

1

Patches

1
b167c43c27c4

improve performance of data url parsing in addimage (#3843)

https://github.com/parallax/jsPDFLukas HolländerMar 17, 2025via ghsa
5 files changed · +26 27
  • package.json+1 1 modified
    @@ -92,7 +92,7 @@
         "version": "yarpm run build && yarpm run generate-docs && git add -A dist docs",
         "pretest": "yarpm run build",
         "test": "yarpm run test-node && yarpm run test-ci",
    -    "test-ci": "karma start test/unit/karma.conf.js --single-run --verbose && for a in coverage/*; do codeclimate-test-reporter < \\\"$a/lcov.info\\\"; break; done",
    +    "test-ci": "karma start test/unit/karma.conf.js --browsers=ChromeHeadless --single-run --verbose && for a in coverage/*; do codeclimate-test-reporter < \\\"$a/lcov.info\\\"; break; done",
         "test-local": "yarpm run test-unit && yarpm run test-node && yarpm run test-amd && yarpm run test-esm && yarpm run test-globals && yarpm run test-typescript && yarpm run test-webworker",
         "test-unit": "karma start test/unit/karma.conf.js --single-run",
         "test-amd": "karma start test/deployment/amd/karma.conf.js --single-run",
    
  • src/modules/addimage.js+23 23 modified
    @@ -641,32 +641,34 @@ import { atob, btoa } from "../libs/AtobBtoa.js";
        * @name extractImageFromDataUrl
        * @function
        * @param {string} dataUrl a valid data URI of format 'data:[<MIME-type>][;base64],<data>'
    -   * @returns {Array}an Array containing the following
    -   * [0] the complete data URI
    -   * [1] <MIME-type>
    -   * [2] format - the second part of the mime-type i.e 'png' in 'image/png'
    -   * [4] <data>
    +   * @returns {string} The raw Base64-encoded data.
        */
       var extractImageFromDataUrl = (jsPDFAPI.__addimage__.extractImageFromDataUrl = function(
         dataUrl
       ) {
    -    dataUrl = dataUrl || "";
    -    var dataUrlParts = dataUrl.split("base64,");
    -    var result = null;
    +    if (dataUrl == null) {
    +      return null;
    +    }
     
    -    if (dataUrlParts.length === 2) {
    -      var extractedInfo = /^data:(\w*\/\w*);*(charset=(?!charset=)[\w=-]*)*;*$/.exec(
    -        dataUrlParts[0]
    -      );
    -      if (Array.isArray(extractedInfo)) {
    -        result = {
    -          mimeType: extractedInfo[1],
    -          charset: extractedInfo[2],
    -          data: dataUrlParts[1]
    -        };
    -      }
    +    // avoid using a regexp for parsing because it might be vulnerable against ReDoS attacks
    +
    +    dataUrl = dataUrl.trim();
    +
    +    if (!dataUrl.startsWith("data:")) {
    +      return null;
         }
    -    return result;
    +
    +    const commaIndex = dataUrl.indexOf(",");
    +    if (commaIndex < 0) {
    +      return null;
    +    }
    +
    +    const dataScheme = dataUrl.substring(0, commaIndex).trim();
    +    if (!dataScheme.endsWith("base64")) {
    +      return null;
    +    }
    +
    +    return dataUrl.substring(commaIndex + 1);
       });
     
       /**
    @@ -942,13 +944,11 @@ import { atob, btoa } from "../libs/AtobBtoa.js";
         throwError
       ) {
         throwError = typeof throwError === "boolean" ? throwError : true;
    -    var base64Info;
         var imageData = "";
         var rawData;
     
         if (typeof stringData === "string") {
    -      base64Info = extractImageFromDataUrl(stringData);
    -      rawData = base64Info !== null ? base64Info.data : stringData;
    +      rawData = extractImageFromDataUrl(stringData) ?? stringData;
     
           try {
             imageData = atob(rawData);
    
  • test/reference/bar_graph_with_text_and_lines.pdf+0 0 modified
  • test/specs/base64.spec.js+1 2 modified
    @@ -38,8 +38,7 @@ describe("Module: addimage bas64Validation", () => {
     
         const doc = new jsPDF("p", "pt", "a4", false);
         const data = doc.__addimage__.extractImageFromDataUrl(blackpixel);
    -    expect(data.mimeType).toBe("image/jpeg");
    -    expect(data.data).toBe(
    +    expect(data).toBe(
           "/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCAABAAEDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD+f+iiigD/2Q=="
         );
         expect(doc.__addimage__.extractImageFromDataUrl()).toBe(null);
    
  • test/specs/html.spec.js+1 1 modified
    @@ -124,7 +124,7 @@ describe("Module: html", () => {
         );
       });
     
    -  it("renders font-faces", async () => {
    +  xit("renders font-faces", async () => {
         const opts = {
           fontFaces: [
             {
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.