CVE-2026-88976 Overview
CVE-2026-88976 is a Cross-Site Scripting (XSS) vulnerability in Plate, a rich-text editor built with AI and shadcn/ui components. The flaw affects versions prior to 53.3.11, along with the discontinued 54.0.0-beta.0 through 54.0.0-beta.1 builds. Plate's core HTML deserialization APIs parse supplied HTML strings inside the active document. When an application passes untrusted or cross-user HTML to these APIs, certain HTML attributes trigger browser behavior before the HTML is converted into editor nodes. Attacker-controlled script can then execute in the consuming application's origin when another user loads the deserialized content. The issue is fixed in version 53.3.11 and maps to [CWE-79].
Critical Impact
Attacker-supplied HTML can execute JavaScript in the victim's browser session within the hosting application's origin, enabling session theft or content manipulation.
Affected Products
- Plate rich-text editor versions prior to 53.3.11
- Plate 54.0.0-beta.0 (discontinued beta build)
- Plate 54.0.0-beta.1 (discontinued beta build)
Discovery Timeline
- 2026-09-16 - CVE CVE-2026-88976 published to NVD
- 2026-09-16 - Last updated in NVD database
Technical Details for CVE-2026-88976
Vulnerability Analysis
The vulnerability resides in Plate's HTML-to-editor deserialization pipeline. Two functions, htmlStringToDOMNode and getEditorDOMFromHtmlString, converted raw HTML strings into DOM structures by assigning innerHTML on a live <body> element created via document.createElement('body'). Because the resulting node is attached to the active document context, the browser evaluates attribute handlers such as onerror and onload on elements like <img> and <iframe> during parsing. Any script defined in those attributes runs immediately in the consuming application's origin, before Plate ever transforms the HTML into safe editor nodes. A collaborator, comment author, or pasted document containing crafted markup can deliver script that runs when another user loads the shared content.
Root Cause
The root cause is unsafe HTML parsing in an active browsing context. Assigning untrusted HTML to innerHTML on a node in the live document triggers resource-loading side effects that fire inline event handlers. Plate's sanitization occurred after this parsing step, so script execution preceded any node filtering [CWE-79].
Attack Vector
An attacker authors HTML containing an event-handler payload, for example an <img> element with an onerror attribute pointing at a broken source. The attacker submits this HTML through any application feature that stores or shares content between users. When a second user opens the document, Plate deserializes the HTML string and the browser fires the handler in that user's session.
// Security patch: parse HTML in an inert document instead of the live body.
// Source: https://github.com/udecode/plate/commit/d02afe45d5ec3a9fb95e0745bc5820ff18a3c12b
-/** Convert HTML string into HTML element. */
-export const htmlStringToDOMNode = (rawHtml: string) => {
- const node = document.createElement('body');
- node.innerHTML = rawHtml;
+import { parseHtmlDocument } from './parseHtmlDocument';
- return node;
-};
+/** Convert HTML string into HTML element. */
+export const htmlStringToDOMNode = (rawHtml: string) =>
+ parseHtmlDocument(rawHtml).body;
// packages/core/src/static/deserialize/htmlStringToEditorDOM.ts
export const getEditorDOMFromHtmlString = (html: string) => {
- const node = document.createElement('body');
- node.innerHTML = html;
- const editorNode = node.querySelector('[data-slate-editor="true"]');
+ const document = new DOMParser().parseFromString(html, 'text/html');
+ const editorNode = document.querySelector('[data-slate-editor="true"]');
return editorNode as HTMLElement;
};
The patched code uses DOMParser().parseFromString(html, 'text/html'), which produces an inert document where resource requests and event handlers do not fire. See GitHub Pull Request #5117 for the full change set.
Detection Methods for CVE-2026-88976
Indicators of Compromise
- Stored HTML content containing inline event-handler attributes such as onerror, onload, onclick, or onmouseover on tags including <img>, <iframe>, <svg>, and <video>.
- Outbound browser requests to attacker-controlled domains originating from application origins that render Plate content.
- Unexpected cookie or token exfiltration from user sessions viewing shared editor documents.
Detection Strategies
- Audit stored documents and comments for HTML payloads containing on*= attribute patterns or javascript: URLs.
- Inspect application dependency manifests for @udecode/plate* packages at versions below 53.3.11 or the 54.0.0-beta.0/54.0.0-beta.1 builds.
- Enable Content Security Policy (CSP) reporting to capture inline script execution attempts and third-party resource loads.
Monitoring Recommendations
- Log and alert on CSP script-src violations and img-src violations from pages that render Plate content.
- Monitor web application firewall (WAF) logs for HTML uploads containing event-handler attributes on image and iframe tags.
- Track session anomalies such as sudden token reuse from new IP addresses following document-sharing activity.
How to Mitigate CVE-2026-88976
Immediate Actions Required
- Upgrade Plate to version 53.3.11 or later in all consuming applications.
- Discontinue use of the 54.0.0-beta.0 and 54.0.0-beta.1 builds, which the maintainers have abandoned.
- Review and sanitize existing stored HTML content generated by unpatched Plate versions.
Patch Information
The fix ships in Plate 53.3.11. It replaces innerHTML assignment on a live <body> element with DOMParser.parseFromString(..., 'text/html'), ensuring HTML is parsed in an inert document that does not execute event handlers or fetch external resources. Details are available in the GitHub Security Advisory GHSA-qrfj-mgw8-j9c6 and the GitHub Release v53.3.11.
Workarounds
- Apply server-side or client-side HTML sanitization (for example, DOMPurify) to all user-supplied HTML before passing it to Plate deserialization APIs.
- Deploy a strict Content Security Policy that disallows inline scripts and restricts image and iframe sources to trusted origins.
- Restrict who can share rich-text content across user boundaries until the upgrade is deployed.
# Upgrade Plate core packages to the patched release
npm install @udecode/plate-core@^53.3.11
# Verify no vulnerable versions remain in the dependency tree
npm ls @udecode/plate-core
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

