Oct 28, 2026·9 min read·1 visit
An incomplete data: URI blocklist and insufficient C0 control character filtering in CKEditor 5's ViewDomConverter allow Cross-Site Scripting (XSS) when General HTML Support permits <object>, <embed>, or <iframe> elements. Upgrade to CKEditor 5 v48.5.1 or v47.7.4 (LTS).
CVE-2026-116687 is a Cross-Site Scripting (XSS) vulnerability in the @ckeditor/ckeditor5-engine package of CKEditor 5. When the General HTML Support (GHS) plugin is configured to permit embedded container elements such as <object>, <embed>, or <iframe>, insufficient validation of data: URIs and incomplete stripping of ASCII C0 control characters allow attackers to execute arbitrary JavaScript within an isolated null-origin browser context.
CKEditor 5 is a modular rich-text editor framework written in TypeScript. Its core rendering pipeline relies on the @ckeditor/ckeditor5-engine package, which maintains an abstract virtual representation of the document and translates it into actual browser Document Object Model (DOM) nodes via the ViewDomConverter class. To support custom or legacy HTML markup not natively handled by dedicated editor plugins, CKEditor 5 provides the General HTML Support (GHS) plugin.
CVE-2026-116687 (also tracked as GHSA-v6mg-96c6-gmpq) is a Cross-Site Scripting (CWE-79) vulnerability within the ViewDomConverter attribute sanitization routine. The vulnerability is exposed when an application enables the General HTML Support plugin and explicitly configures it to allow document-embedding elements such as <object>, <embed>, or <iframe> along with their resource-loading attributes (data or src).
When rendering view elements into the editing DOM, ViewDomConverter.shouldRenderAttribute() inspects URI-bearing attributes to prevent the injection of executable schemes like javascript: or active data: payloads. Prior to versions 48.5.1 and 47.7.4, this sanitization relied on a narrow regular expression blocklist and incomplete whitespace stripping.
An authenticated user with privileges to input or paste HTML content into a vulnerable CKEditor 5 instance can bypass the attribute filter using unhandled XML-based data: MIME types or leading ASCII C0 control characters. When the editor converts the virtual view into the live DOM, the browser instantiates an active sub-document and executes the attacker's JavaScript payload within a null (opaque) origin context.
The root cause of CVE-2026-116687 resides in packages/ckeditor5-engine/src/view/domconverter.ts within the ViewDomConverter.shouldRenderAttribute() method. This method acts as a security boundary between the editor's internal view tree and the browser's native DOM APIs. It evaluates attribute names and values to determine whether an attribute can be safely attached to a DOM element or if it must be neutralized by prefixing it with data-ck-unsafe-attribute-.
The first flaw in shouldRenderAttribute() was the use of an incomplete denylist for data: URIs: /^(javascript:|data:(image\/svg|text\/x?html))/i. While this expression blocked data:image/svg+xml, data:text/html, and data:text/xhtml, modern web browsers support script execution across a much wider array of XML-based MIME types when loaded inside container elements like <object>, <embed>, or <iframe>. Specifically, browsers instantiate an XML document parser capable of executing <script> blocks or inline SVG event handlers for text/xml, application/xml, application/xhtml+xml, text/xsl, application/rss+xml, application/atom+xml, and any arbitrary MIME subtype carrying the +xml structured syntax suffix (such as image/png+xml).
The second flaw involved a mismatch between JavaScript regular expression character classes and the WHATWG URL Standard regarding control character normalization. Before testing the attribute value against the scheme blocklist, the engine stripped whitespace using attributeValue.replace(/\s+/g, ''). In ECMAScript regular expressions, the \s metacharacter matches standard ASCII whitespace (0x09–0x0D and 0x20) and Unicode space separators, but it does not match remaining ASCII C0 control characters (0x00–0x08 and 0x0E–0x1F).
According to the WHATWG URL parsing specification implemented by modern browser engines, all leading and trailing C0 control characters and spaces (0x00 through 0x20) are stripped from a URL input string before extracting the scheme component. Consequently, an attribute value prefixed with a control character such as \u0001 (e.g., data:text/html,... or javascript:...) retained the \u0001 byte after replace(/\s+/g, ''). Because the regular expression anchored the match to the start of the string with ^, the check failed to match, shouldRenderAttribute() returned true, and the browser subsequently stripped the \u0001 byte and executed the URI.
The vulnerability was remediated in commits 4d9c5bb34f63cd956d15ccafbe584e14280c86a0 (for the 48.x release branch) and a750e38635db6a18c5b11599c09f4fd702850423 (for the 47.x LTS branch). The patch modifies packages/ckeditor5-engine/src/view/domconverter.ts to address both the C0 control character evasion and the incomplete MIME type filtering.
In the unpatched implementation, shouldRenderAttribute() attempted to strip whitespace and match dangerous schemes in a single conditional statement:
// Vulnerable code prior to 48.5.1 / 47.7.4
if ( attributeValue.replace( /\s+/g, '' ).match( /^(javascript:|data:(image\/svg|text\/x?html))/i ) ) {
return false;
}
return true;The patched implementation replaces the character stripping regex and swaps the data: URI denylist for a strict allowlist of known-safe binary media formats:
// Patched code in 48.5.1 / 47.7.4
// 1. Strip both standard whitespace and all ASCII C0 control characters (0x00 - 0x20)
// eslint-disable-next-line no-control-regex
attributeValue = attributeValue.replace( /[\s\u0000-\u0020]+/g, '' );
// 2. Explicitly reject javascript: URIs
if ( attributeValue.match( /^javascript:/i ) ) {
return false;
}
// 3. Enforce a strict allowlist for data: URIs
if ( attributeValue.match( /^data:/i ) ) {
const isImage = attributeValue.match(
/^data:image\/(png|jpeg|jpg|gif|webp|avif|bmp|x-icon|vnd\.microsoft\.icon|apng|tiff|heic|heif|jxl)($|[;,])/i
);
const isMedia = attributeValue.match(
/^data:(audio|video)\/(mp4|mpeg|mp3|ogg|webm|wav|x-wav|aac|flac|quicktime|3gpp)($|[;,])/i
);
if ( !isImage && !isMedia ) {
return false;
}
}
return true;> [!NOTE]
> The regular expressions for isImage and isMedia terminate the MIME subtype match with ($|[;,]). This boundary assertion is critical for fix completeness: a simple prefix match on data:image/png would inadvertently permit data:image/png+xml;base64,..., which browsers parse as an executable XML document due to the +xml suffix.
The fix is comprehensive with respect to data: and javascript: URI handling. By restricting data: URIs exclusively to raster images and binary audio/video formats—which are processed by media decoders rather than HTML/XML document parsers—the patch eliminates the possibility of script execution even when the URI is loaded inside an <iframe>, <object>, or <embed> element.
Exploiting CVE-2026-116687 requires specific application-level prerequisites. By default, CKEditor 5 strips unrecognized HTML elements and attributes. For the vulnerable code path to become reachable with an active container element, the host application must include the GeneralHtmlSupport plugin and configure its htmlSupport.allow rules to permit elements capable of loading external or inline sub-documents (<object>, <embed>, or <iframe>).
// Prerequisite configuration exposing the attack surface
ClassicEditor.create( document.querySelector( '#editor' ), {
plugins: [ GeneralHtmlSupport, /* other plugins */ ],
htmlSupport: {
allow: [
{
name: /^(object|embed|iframe)$/
attributes: true
}
]
}
} );When this configuration is active, an attacker with permissions to author or edit content can inject crafted markup through source editing mode, clipboard paste operations, or API data loading (editor.setData()). The vendor regression test suite demonstrates three primary exploitation vectors.
<iframe> or <object>By specifying data:text/xml or data:application/xml, the attacker evades the /^data:(image\/svg|text\/x?html)/i filter. The base64 payload decodes to an XML document containing an SVG element with an onload event handler or <script> tag:
<!-- Decodes to: <svg xmlns='http://www.w3.org/2000/svg' onload='alert(1)'/> -->
<iframe src="data:text/xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIG9ubG9hZD0nYWxlcnQoMSknLz4="></iframe>
<!-- Decodes to: <svg xmlns="http://www.w3.org/2000/svg"><script>alert(document.domain)</script></svg> -->
<object data="data:application/xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxzY3JpcHQ+YWxlcnQoZG9jdW1lbnQuZG9tYWluKTwvc2NyaXB0Pjwvc3ZnPg=="></object>+xml) BypassBrowsers treat any MIME type ending in +xml as an XML document. An attacker can append +xml to an otherwise benign MIME prefix to bypass naive blocklists:
<object data="data:image/png+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmci onload="alert(1)"/>"></object>By inserting a numeric character reference for an ASCII C0 control character (such as  for Start of Heading 0x01) at the beginning of the attribute value, the attacker bypasses regexes anchored with ^ that only strip standard whitespace (\s+):
<iframe src="data:text/html,<script>alert(1)</script>"></iframe>When CKEditor 5 parses the HTML entity  into the literal character \u0001 in the virtual view and passes it to shouldRenderAttribute(), the check fails to detect the data:text/html prefix. The attribute is written directly to the DOM, where the browser's URL parser strips \u0001 and renders the HTML document.
The severity of CVE-2026-116687 is rated as Low with a CVSS v3.1 base score of 3.1 (CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N). The Attack Complexity is marked High (AC:H) because exploitation depends on a non-default configuration of the General HTML Support plugin that permits arbitrary embedded container tags.
Furthermore, the security impact of the script execution is constrained by modern web browser architecture. When an <iframe>, <object>, or <embed> element loads a document via a data: URI, the browser assigns the resulting browsing context a unique, opaque origin (origin: null). Because of the Same-Origin Policy (SOP), scripts executing inside a null origin are isolated from the parent window's origin.
Concretely, JavaScript executing via these data: URI vectors cannot access window.parent.document, cannot read document.cookie belonging to the host application, and cannot read localStorage or sessionStorage of the embedding site. This browser-level isolation sets the Confidentiality Impact to None (C:N) and keeps the Scope Unchanged (S:U).
However, if the C0 control character bypass (javascript:...) is used on an <iframe src> or an interactive link attribute (<a href>), or if an attacker uses the isolated data: frame to render spoofed UI elements inside the editor canvas, integrity is impacted (I:L). Attackers can perform UI redressing, display phishing forms within the trusted editor boundary, or trigger top-level navigation and file downloads depending on the host application's Content Security Policy (CSP) and iframe sandboxing rules.
To remediate CVE-2026-116687, organizations and developers should upgrade their ckeditor5 and @ckeditor/ckeditor5-engine packages to the patched releases.
48.5.1 or later.47.7.4 or later.Developers managing dependencies via npm can apply the update using:
npm install ckeditor5@^48.5.1 @ckeditor/ckeditor5-engine@^48.5.1
# Or for LTS users:
npm install ckeditor5@^47.7.4 @ckeditor/ckeditor5-engine@^47.7.4If an immediate package upgrade is not possible, administrators can mitigate the vulnerability by modifying the CKEditor 5 configuration to explicitly disallow <object>, <embed>, and <iframe> elements within the General HTML Support (GHS) plugin configuration:
ClassicEditor.create( document.querySelector( '#editor' ), {
plugins: [ GeneralHtmlSupport, /* ... */ ],
htmlSupport: {
disallow: [
{
name: /^(object|embed|iframe)$/
}
]
}
} );As a defense-in-depth measure, web applications embedding CKEditor 5 should deploy a restrictive Content Security Policy (CSP) header that disables <object> and <embed> elements entirely and restricts child frame sources to trusted origins:
Content-Security-Policy: object-src 'none'; frame-src 'self';CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
ckeditor5 CKSource | >= 29.0.0, < 47.7.4 | 47.7.4 |
ckeditor5 CKSource | >= 48.0.0, < 48.5.1 | 48.5.1 |
@ckeditor/ckeditor5-engine CKSource | >= 29.0.0, < 47.7.4 | 47.7.4 |
@ckeditor/ckeditor5-engine CKSource | >= 48.0.0, < 48.5.1 | 48.5.1 |
| Attribute | Detail |
|---|---|
| Vulnerability Type | Cross-Site Scripting (CWE-79) |
| Affected Component | @ckeditor/ckeditor5-engine (ViewDomConverter) |
| CVSS v3.1 Score | 3.1 Low (AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N) |
| Attack Prerequisites | General HTML Support (GHS) enabled allowing <object>, <embed>, or <iframe> |
| Execution Context | Opaque (null) browser origin inside embedded container |
| Patched Versions | 48.5.1 and 47.7.4 (LTS) |
| Exploit Status | Proof-of-Concept in vendor regression tests |
| CISA KEV Status | Not Listed |
The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVE-2026-116686 is a Server-Side Request Forgery (SSRF) and Denial of Service (DoS) vulnerability in the official Model Context Protocol (MCP) Python SDK (mcp package on PyPI). When an MCP client validates structured tool execution results against a server-provided outputSchema, the SDK invokes the Python jsonschema library with its default URI resolution configuration. An untrusted or compromised MCP server can supply an outputSchema containing external $ref directives (using http://, https://, or file:// schemes), forcing the client process to synchronously fetch internal network resources, read local files, or block the main event loop indefinitely.
CVE-2026-116685 (GHSA-5h93-6whr-6q8j) is a sensitive information disclosure vulnerability in the official Model Context Protocol (MCP) Python SDK (`mcp` on PyPI). In versions 1.8.0 through 1.29.1 and 2.0.0 through 2.1.1, the SDK's HTTP-based client transports—including Streamable HTTP, Server-Sent Events (SSE), and OAuth client flows—unconditionally enable automatic HTTP redirect following (`follow_redirects=True`) across origin boundaries. When a configured endpoint returns a redirect to an external origin, the HTTP client forwards caller-supplied custom authentication headers (such as `X-API-Key`) and, in the case of HTTP 307 or 308 responses, replays the full POST request body containing JSON-RPC payloads or OAuth parameters to the untrusted destination.
CVE-2026-116694 (GHSA-f5m9-jfrj-jjj7) is an unbounded resource allocation vulnerability (CWE-770) in the optional Jaeger propagator component (opentelemetry-propagator-jaeger) of the OpenTelemetry Python SDK prior to version 1.45.0. When extracting distributed tracing context from inbound carriers, JaegerPropagator.extract() processes all headers prefixed with 'uberctx-' without enforcing limits on entry count, per-entry byte size, or aggregate byte size. In environments where transport-level header constraints are absent, relaxed, or bypassed (such as non-HTTP message brokers, RPC frameworks, or web servers with elevated buffer configurations), an unauthenticated remote attacker can supply high-volume or oversized baggage headers to trigger excessive URL unquoting, short-lived immutable dictionary allocations, and CPU starvation.
CVE-2026-116684 is an incorrect authorization vulnerability (CWE-863) in the Model Context Protocol (MCP) Python SDK (`modelcontextprotocol/python-sdk`). The server-side bearer authentication middleware (`BearerAuthBackend`) verifies token cryptographic signatures and expiration timestamps via `TokenVerifier`, but fails to verify that the token's audience (`aud` claim or RFC 8707 resource indicator) matches the receiving MCP server's configured `resource_server_url`. In multi-service environments sharing a single OAuth 2.0 Authorization Server, an attacker possessing a valid token for an unrelated service can replay it against the MCP server to gain unauthorized access to protected tools, resources, and prompts.
CVE-2026-116675 is a stored Cross-Site Scripting (XSS) vulnerability in the TinyMCE rich text editor affecting versions 7.9.3 and 8.5.1 through 8.9.2. The flaw resides in the media plugin's serialization logic, where placeholder elements configured with the data-mce-object attribute are converted into real DOM elements using the active window's document context prior to sanitization. When an attacker supplies a media element with an invalid source attribute alongside an inline event handler attribute such as data-mce-p-onerror, the browser resolves the resource and executes the malicious JavaScript before the sanitizer can strip the dangerous attributes.
CVE-2026-116693 is a high-severity Regular Expression Denial of Service (ReDoS) vulnerability affecting the official Datadog Application Performance Monitoring (APM) client library for Node.js, dd-trace. The defect resides in the default regular expression defined by the DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP configuration parameter, which is used to sanitize incoming and outgoing HTTP URL query strings prior to recording trace span metadata. Due to overlapping sub-patterns and unanchored repetition blocks in the JSON Web Token (JWT) and URL-encoded string matching branches, the V8 JavaScript engine's regular expression subsystem (Irregexp) can be forced into catastrophic or high-degree polynomial backtracking. Because regular expression replacement occurs synchronously on the primary Node.js event loop, an unauthenticated remote attacker can send crafted HTTP requests with malicious query strings to consume 100% of the process CPU core, stalling concurrent request processing and rendering the application unavailable.