GHSA-87v3-4cfp-cm76: @pdfme/schemas Cross-Site Scripting Vulnerability
MODERATEGHSA-87v3-4cfp-cm76 is a MODERATE (CVSS 6.1) cross-site scripting vulnerability (CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')) affecting @pdfme/schemas libraries in the npm ecosystem. The issue involves cross-site scripting (xss) via svg schema innerhtml injection in @pdfme/schemas. Remediation is available by upgrading affected packages to version 5.5.9.
GHSA-87v3-4cfp-cm76 at a Glance
Security Impact
CVSS: 6.1
The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N).
How to Fix GHSA-87v3-4cfp-cm76
To remediate this vulnerability, upgrade all affected @pdfme/schemas dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
npm install @pdfme/schemas@5.5.9
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
npm ls @pdfme/schemas
How to Check if You Are Affected
To determine whether your Node.js application is affected by GHSA-87v3-4cfp-cm76, inspect your project dependencies using npm:
npm ls @pdfme/schemas
Analyze the terminal output to locate any version of @pdfme/schemas in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 5.5.9), your application is affected.
Note: The npm ls @pdfme/schemas command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting'), where the product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users. In @pdfme/schemas, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
GHSA-87v3-4cfp-cm76 Affected @pdfme/schemas Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
@pdfme/schemas
|
npm |
< 5.5.9
|
5.5.9
|
References
Frequently Asked Questions
What is GHSA-87v3-4cfp-cm76?
Which @pdfme/schemas versions are affected?
What version fixes GHSA-87v3-4cfp-cm76?
Is @pdfme/schemas affected?
What is the CVSS score of GHSA-87v3-4cfp-cm76?
What CWE is associated with GHSA-87v3-4cfp-cm76?
How can I check npm dependencies for GHSA-87v3-4cfp-cm76?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-87v3-4cfp-cm76",
"modified" : "2026-03-18T16:10:26Z",
"published" : "2026-03-18T16:10:26Z",
"aliases" : [ ],
"summary" : "Cross-Site Scripting (XSS) via SVG Schema innerHTML Injection in @pdfme/schemas",
"details" : "## Summary\n\nThe SVG schema plugin in `@pdfme/schemas` renders user-supplied SVG content using `container.innerHTML = value` without any sanitization, enabling arbitrary JavaScript execution in the user's browser.\n\n## Details\n\nIn `packages/schemas/src/graphics/svg.ts`, line 87, the SVG schema's `ui` renderer assigns raw SVG markup directly to `innerHTML` when in viewer mode or form mode with `readOnly: true`:\n\n```typescript\n// svg.ts, line 81-94 (non-editable rendering path)\n} else {\n if (!value) return;\n if (!isValidSVG(value)) {\n rootElement.appendChild(createErrorElm());\n return;\n }\n container.innerHTML = value; // <-- VULNERABLE: unsanitized SVG injected into DOM\n const svgElement = container.childNodes[0];\n if (svgElement instanceof SVGElement) {\n svgElement.setAttribute('width', '100%');\n svgElement.setAttribute('height', '100%');\n rootElement.appendChild(container);\n }\n}\n```\n\nThe `isValidSVG()` function (lines 11-37) only validates that the string contains `<svg` and `</svg>` tags and passes `DOMParser` well-formedness checks. It does NOT strip or block:\n- `<script>` tags embedded in SVG\n- Event handler attributes (`onload`, `onerror`, `onclick`, etc.)\n- `<foreignObject>` elements containing HTML with event handlers\n- `<animate>` / `<set>` elements with `onbegin` / `onend` handlers\n- SVG `<use>` elements referencing malicious external resources\n\nAll of these are valid SVG and pass `isValidSVG()`, but execute JavaScript when inserted via `innerHTML`.\n\n## Attack Vectors\n\n### 1. Malicious Template (readOnly SVG schema)\nAn attacker crafts a template JSON with a readOnly SVG schema containing a malicious `content` value. When loaded into the pdfme Form or Viewer component, the SVG executes JavaScript.\n\n### 2. Application-Supplied Inputs + Viewer\nIf an application uses the pdfme Viewer component and passes user-controlled data as inputs for a non-readOnly SVG schema, the attacker's SVG flows directly to `innerHTML`.\n\n## Proof of Concept\n\nLoading the following template into a pdfme Form or Viewer component triggers JavaScript execution:\n\n```json\n{\n \"basePdf\": { \"width\": 210, \"height\": 297, \"padding\": [20, 20, 20, 20] },\n \"schemas\": [[\n {\n \"name\": \"malicious_svg\",\n \"type\": \"svg\",\n \"content\": \"<svg xmlns='http://www.w3.org/2000/svg' onload='alert(document.domain)'><rect width='100' height='100' fill='red'/></svg>\",\n \"readOnly\": true,\n \"position\": { \"x\": 20, \"y\": 20 },\n \"width\": 80,\n \"height\": 40\n }\n ]]\n}\n```\n\nAdditional payloads that bypass `isValidSVG()` and execute JavaScript:\n\n```svg\n<!-- Via foreignObject -->\n<svg xmlns=\"http://www.w3.org/2000/svg\"><foreignObject width=\"200\" height=\"60\"><body xmlns=\"http://www.w3.org/1999/xhtml\"><img src=\"x\" onerror=\"alert(1)\"/></body></foreignObject></svg>\n\n<!-- Via animate onbegin -->\n<svg xmlns=\"http://www.w3.org/2000/svg\"><rect width=\"100\" height=\"100\"><animate attributeName=\"x\" values=\"0\" dur=\"0.001s\" onbegin=\"alert(1)\"/></rect></svg>\n```\n\n## Impact\n\nAn attacker who can supply a malicious template (via file upload, shared template URL, multi-tenant template storage, or `updateTemplate()` API) can execute arbitrary JavaScript in the context of any user who views or fills the template. This enables:\n- Session hijacking via cookie/token theft\n- Keylogging of form inputs (including sensitive data being entered into PDF forms)\n- Phishing attacks by modifying the rendered page\n- Data exfiltration from the application\n\nThe attack is particularly concerning for multi-tenant SaaS applications using pdfme where templates may be user-supplied.\n\n## Suggested Fix\n\nSanitize SVG content before DOM insertion using DOMPurify or a similar library:\n\n```typescript\nimport DOMPurify from 'dompurify';\n\n// Replace line 87:\ncontainer.innerHTML = DOMPurify.sanitize(value, { USE_PROFILES: { svg: true } });\n```\n\nAlternatively, parse the SVG via `DOMParser`, strip all script elements and event handler attributes, then append the sanitized DOM nodes.",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "npm",
"name" : "@pdfme/schemas"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "5.5.9"
} ]
} ],
"database_specific" : {
"last_known_affected_version_range" : "<= 5.5.8"
}
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/pdfme/pdfme/security/advisories/GHSA-87v3-4cfp-cm76"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/pdfme/pdfme"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-79" ],
"severity" : "MODERATE",
"github_reviewed" : true,
"github_reviewed_at" : "2026-03-18T16:10:26Z",
"nvd_published_at" : null
}
}