CVE-2026-55090: Etherpad Stored XSS via Unescaped HTML Export Attribute Values
Any pad collaborator with write access can inject a crafted attribute value into the pad's attribute pool that, when another user exports the pad as HTML, executes arbitrary JavaScript in their…

The problem
Etherpad's getHTMLFromAtext function in src/node/utils/ExportHtml.ts builds <span data-<k>="<v>"> elements from values registered by the exportHtmlAdditionalTagsWithData plugin hook. Neither the attribute name nor the value was HTML-attribute-escaped before being written into the export output.
The values come verbatim from the pad attribute pool. A pad editor controls the pool via crafted changesets: only author attributes are validated, so AttributePool.putAttrib stores any arbitrary string. With a bundled plugin that registers the hook (for example ep_font_color or ep_font_size), the injected value lands in the exported HTML file served as text/html, giving stored XSS to every collaborator who opens the export.
Proof of concept
A working proof-of-concept for CVE-2026-55090 in ep_etherpad-lite, with the exact payload below.
<!-- Attacker submits a changeset that stores this attribute pair in the pad's attribute pool:
key: color
value: " onmouseover="alert(document.cookie)"
ExportHtml.ts renders it verbatim, producing: -->
<span data-color="" onmouseover="alert(document.cookie)">text</span>The root cause is missing output encoding (CWE-79). Before the fix, ExportHtml.ts concatenated key and value directly into the attribute string with no call to Security.escapeHTMLAttribute. A value containing " (double-quote) terminates the data attribute early and injects arbitrary HTML attributes or event handlers.
PR #7905 wraps both k and v in Security.escapeHTMLAttribute(...) before interpolation, so " becomes " and injection is impossible. The patch also escapes the attribute name (k), closing a secondary injection if a plugin were to register a key containing special characters.
The fix
Upgrade to **ep_etherpad-lite 3.3.0** (Etherpad release tag 3.3.0, commit 86c56cf). The fix is in PR #7905. There is no safe configuration workaround for older versions: the only mitigation short of upgrading is to disable all plugins that register exportHtmlAdditionalTagsWithData (such as ep_font_color and ep_font_size) and to block access to the /p/*/export/html endpoint.
Related research
- high · 7.5CVE-2026-53950CVE-2026-53950: @tryghost/activitypub Stored XSS via Federated Post Content
- highCVE-2026-69149CVE-2026-69149: @angular/platform-server SSR Fallback Raw-Content XSS
- highCVE-2026-69151CVE-2026-69151: @angular/compiler i18n Event-Handler Attribute XSS
- high · 8.7CVE-2026-53608CVE-2026-53608: @apostrophecms/seo Stored XSS via Unsanitized Google Analytics ID