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.
| Package | Affected versions | Patched versions |
|---|---|---|
jspdfnpm | < 3.0.1 | 3.0.1 |
Affected products
1Patches
1b167c43c27c4improve performance of data url parsing in addimage (#3843)
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 modifiedtest/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- github.com/advisories/GHSA-w532-jxjh-hjhjghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-29907ghsaADVISORY
- github.com/parallax/jsPDF/commit/b167c43c27c466eb914b927885b06073708338dfghsax_refsource_MISCWEB
- github.com/parallax/jsPDF/security/advisories/GHSA-w532-jxjh-hjhjghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.