@eigenpal/docx-editor-core: CSS Injection and Print-Time XSS via Unescaped Font Name
A crafted .docx file with a malicious embedded font name injects attacker-controlled CSS into any page that opens the file, and escalates to full script execution the moment a user clicks Print.

The problem
The core parser reads font-family names from word/fontTable.xml and drops them verbatim into an injected @font-face <style> block. No sanitisation or escaping is applied, so any string that is legal XML is also legal as the injected value.
On open, a crafted name applies page-wide CSS with zero user interaction: overlay phishing, attribute-selector credential exfiltration, or tracking beacons are all viable. Clicking Print escalates the impact: the same font name is interpolated into document.write() inside the print window, where closing the <style> tag with </style> lets arbitrary HTML, including <script>, execute in the embedder's origin.
Proof of concept
A working proof-of-concept for this issue in @eigenpal/docx-editor-core, with the exact payload below.
<!-- word/fontTable.xml inside the crafted .docx -->
<w:fonts xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:font w:name="Evil}</style><img src=x onerror=alert(document.domain)><style>/*">
<w:charset w:val="00"/>
</w:font>
</w:fonts>
<!-- What the library injected on open (CSS injection only): -->
<style>
@font-face {
font-family: 'Evil}</style><img src=x onerror=alert(document.domain)><style>/*';
src: local('Evil...</style>
<!-- What the library injected on Print (document.write, full XSS): -->
document.write(
'<style>@font-face { font-family: "Evil}</style><img src=x onerror=alert(document.domain)><style>/*"; }</style>'
);The root cause is CWE-79: user-controlled data (the XML font name) flows directly into two HTML sinks with no escaping. In the <style> injection path, the string }</style> closes the CSS block and the <style> tag simultaneously, promoting the payload from CSS context into HTML context.
In the document.write path the same trick works because document.write parses its argument as a full HTML stream, so a closing </style> inside the string terminates the tag and allows inline event handlers to execute.
The fix in 1.8.3 CSS-escapes font names before interpolation, quoting or backslash-escaping characters including <, >, ", ', and CSS newlines. The print window was also rewritten to use DOM APIs (createElement, appendChild) instead of document.write, eliminating the string-parsing sink entirely.
The fix
Upgrade @eigenpal/docx-editor-core (and the React/Vue adapter that depends on it) to version 1.8.3. In 1.8.3 font names are CSS-escaped before interpolation and the print window is built with DOM APIs, closing both injection paths. No workaround exists in 1.8.2 or earlier.
Related research
- high · 8.2CVE-2026-84370CVE-2026-84370: svgo removeScripts Plugin XSS via Namespace and Control-Character Bypass
- critical · 10CVE-2026-85061CVE-2026-85061: maplibre-gl XSS Sanitizer Bypass via Live NamedNodeMap Iteration
- highCVE-2026-54606CVE-2026-54606: suneditor Embed Plugin DOM XSS via External Script Element
- high · 8.7CVE-2026-55596CVE-2026-55596: @platejs/media Media Embed Stored XSS via Serialized Provider Metadata