Date: 2026-03-08 Researcher: Doruk Tan Ozturk (@peaktwilight) - https://doruk.ch
Severity: High
Affected code location: jspdf.umd.js - the pdfobjectnewwindow case in the output() method
Description:
The pdfobjectnewwindow output mode constructs an HTML page containing an inline <script> tag. The options object is serialized using JSON.stringify() and concatenated directly into the script body:
'<script>PDFObject.embed("' + this.output("dataurlstring") + '", ' + JSON.stringify(options) + ");</script>"
JSON.stringify() does not escape </script> sequences. If options.filename contains a </script> string, it breaks out of the script tag context, enabling injection of arbitrary HTML and JavaScript.
Impact: An attacker who controls the filename option can achieve full DOM-based XSS in the context of the page that renders the PDF output.
PoC: See exploit.js (pdfobjectnewwindow variant) attached in this gist.
Suggested fix: Escape all occurrences of </ in the JSON-serialized string before embedding it in the HTML, or use a safe DOM-based approach (e.g., document.createElement) instead of string concatenation into innerHTML/document.write.
Severity: High
Affected code location: jspdf.umd.js / jspdf.node.js - the pdfjsnewwindow case in the output() method
Description:
The pdfjsnewwindow output mode builds an HTML page with an iframe whose src attribute includes the options.filename value without any encoding or escaping:
'<iframe id="pdfViewer" src="' + pdfJsUrl + '?file=&downloadName=' + options.filename + '"...'
A double-quote character in the filename breaks out of the src attribute, allowing injection of arbitrary HTML attributes such as event handlers (e.g., onload="alert(1)").
Impact: An attacker who controls the filename option can inject arbitrary attributes into the iframe element, achieving DOM-based XSS.
PoC: See exploit.js (pdfjsnewwindow variant) attached in this gist.
Suggested fix: Apply proper HTML attribute encoding to options.filename before embedding it in the src attribute. At minimum, encode ", <, >, and & characters.
Vulnerability #3: PDF Object Injection via FreeText Annotation Color (Incomplete fix for CVE-2026-25755)
Severity: High
Affected code location: FreeText annotation handling in jsPDF - the /DS string construction
Description:
This vulnerability represents an incomplete fix for CVE-2026-25755. The jsPDF library concatenates the annotation color value directly into a PDF string literal without escaping parentheses:
line += " /DS(font: ... color:#" + color + ")";
A color value containing ) closes the /DS string early, allowing injection of arbitrary PDF dictionary entries. An attacker can inject /AA (Additional Actions) dictionaries containing JavaScript actions that execute when the annotation is interacted with or the PDF is opened.
Impact: An attacker who controls the color parameter of a FreeText annotation can inject arbitrary PDF objects, including JavaScript actions that execute in PDF viewers that support JavaScript (e.g., Adobe Acrobat).
PoC: See exploit.js (freetext-color-injection variant) attached in this gist.
Suggested fix: Escape parentheses ( and ) in the color value before embedding it in the PDF string literal. All user-supplied values that are placed inside PDF string literals delimited by ( and ) must have those characters escaped with a backslash.
| # | Vulnerability | Severity | CVE |
|---|---|---|---|
| 1 | DOM XSS in pdfobjectnewwindow via JSON.stringify |
High | - |
| 2 | DOM XSS in pdfjsnewwindow via unescaped filename |
High | - |
| 3 | PDF object injection via FreeText annotation color | High | Incomplete fix for CVE-2026-25755 |
All three vulnerabilities stem from insufficient input sanitization when user-controlled values are concatenated into structured output formats (HTML or PDF).