highCVE-2026-55090Aug 17, 2026

CVE-2026-55090: Etherpad Stored XSS via Unescaped HTML Export Attribute Values

Rohit Hatagale
AI Security Researcher, SecureLayer7

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…

Packageep_etherpad-lite
Ecosystemnpm
Affected<= 1.8.14
Fixed in3.3.0
CVE-2026-55090: Etherpad Stored XSS via Unescaped HTML Export Attribute Values

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.

html
<!-- 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 &quot; 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.

Reporter not attributed.

References: [1][2][3][4][5]

Related research