GitHub Advisoryadvisory · npm
GHSA-87v3-4cfp-cm76 Cross-Site Scripting (XSS) via SVG Schema innerHTML Injection in @pdfme/schemas
MEDIUM
Official page ↗
- Ecosystem
- npm
- Packages
- @pdfme/schemas
- Severity
- Moderate
- CVSS vector
- CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
- Weaknesses
- CWE-79
- Reviewed
- 2026-03-18
Affected packages
• npm @pdfme/schemas: < 5.5.9 → fixed in 5.5.9
Description
Summary
The 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.
Details
In `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`:
```typescript
// svg.ts, line 81-94 (non-editable rendering path)
} else {
if (!value) return;
if (!isValidSVG(value)) {
rootElement.appendChild(createErrorElm());
return;
}
container.innerHTML = value; // ` tags and passes `DOMParser` well-formedness checks. It does NOT strip or block:
• `` tags embedded in SVG
• Event handler attributes (`onload`, `onerror`, `onclick`, etc.)
• `` elements containing HTML with event handlers
• `` / `` elements with `onbegin` / `onend` handlers
• SVG `` elements referencing malicious external resources
All of these are valid SVG and pass `isValidSVG()`, but execute JavaScript when inserted via `innerHTML`.
Attack Vectors
1. Malicious Template (readOnly SVG schema)
An 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.
2. Application-Supplied Inputs + Viewer
If 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`.
Proof of Concept
Loading the following template into a pdfme Form or Viewer component triggers JavaScript execution:
```json
{
"basePdf": { "width": 210, "height": 297, "padding": [20, 20, 20, 20] },
"schemas": [[
{
"name": "malicious_svg",
"type": "svg",
"content": "",
"readOnly": true,
"position": { "x": 20, "y": 20 },
"width": 80,
"height": 40
}
]]
}
```
Additional payloads that bypass `isValidSVG()` and execute JavaScript:
```svg
```
Impact
An 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:
• Session hijacking via cookie/token theft
• Keylogging of form inputs (including sensitive data being entered into PDF forms)
• Phishing attacks by modifying the rendered page
• Data exfiltration from the application
The attack is particularly concerning for multi-tenant SaaS applications using pdfme where templates may be user-supplied.
Suggested Fix
Sanitize SVG content before DOM insertion using DOMPurify or a similar library:
```typescript
import DOMPurify from 'dompurify';
// Replace line 87:
container.innerHTML = DOMPurify.sanitize(value, { USE_PROFILES: { svg: true } });
```
Alternatively, parse the SVG via `DOMParser`, strip all script elements and event handler attributes, then append the sanitized DOM nodes.
Related
Weakness · CWE (1)
- CWE-79 Improper Neutralization of Input During Web Page Generation weakness