Cross-Site Scripting (XSS) via Select Schema Option Value Injection in @pdfme/schemas
Date: 2026-03
Affected: npm/@pdfme/schemas
Attack vector: xss
Category: vulnerability-disclosure
Severity: Medium
CWE: CWE-79
CVSS: 6.1 (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N)

## Summary The Select schema plugin in `@pdfme/schemas` constructs HTML from template-defined option values using unsanitized string interpolation and sets it via `innerHTML`, enabling arbitrary JavaScript execution. ## Details In `packages/schemas/src/select/index.ts`, lines 159-164, the Select schema's `ui` renderer builds `<option>` elements by directly interpolating option values from the template into an HTML string: ```typescript const options = Array.isArray(schema.options) ? schema.options : []; selectElement.innerHTML = options .map( (option) => `<option value="${option}" ${option === value ? 'selected' : ''}>${option}</option>`, ) .join(''); ``` The `option` values come from `schema.options`, which is an array of strings defined in the template JSON. These values are interpolated directly into the HTML string without any escaping of `<`, `>`, `"`, `&`, or other HTML-special characters. An option value containing `">` breaks out of the `value` attribute and allows injection of arbitrary HTML elements and event handlers. ## Proof of Concept Loading the following template into a pdfme Form or Designer component triggers JavaScript execution: ```json { "basePdf": { "width": 210, "height": 297, "padding": [20, 20, 20, 20] }, "schemas": [[ { "name": "malicious_select", "type": "select", "content": "Normal", "options": [ "Normal", "\"></option><img src=x onerror=\"alert(document.domain)\">" ],


Mitigations:

Architectural layers (MAESTRO):