CVE-2026-116687: Cross-Site Scripting in CKEditor 5 Engine via Data URI and Control Character Bypass
Vulnerability ID: CVE-2026-116687
CVSS Score: 3.1
Published: 2026-10-27
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 , , or , 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.</p> <h2> <a name="tldr" href="#tldr" class="anchor"> </a> TL;DR </h2> <p>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).</p> <hr> <h3> <a name="exploit-status-poc" href="#exploit-status-poc" class="anchor"> </a> ⚠️ Exploit Status: POC </h3> <h2> <a name="technical-details" href="#technical-details" class="anchor"> </a> Technical Details </h2> <ul> <li><strong>Vulnerability Type</strong>: Cross-Site Scripting (CWE-79)</li> <li><strong>Affected Component</strong>: @ckeditor/ckeditor5-engine (ViewDomConverter)</li> <li><strong>CVSS v3.1 Score</strong>: 3.1 Low (AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N)</li> <li><strong>Attack Prerequisites</strong>: General HTML Support (GHS) enabled allowing <object>, <embed>, or <iframe></li> <li><strong>Execution Context</strong>: Opaque (null) browser origin inside embedded container</li> <li><strong>Patched Versions</strong>: 48.5.1 and 47.7.4 (LTS)</li> <li><strong>Exploit Status</strong>: Proof-of-Concept in vendor regression tests</li> <li><strong>CISA KEV Status</strong>: Not Listed</li> </ul> <h2> <a name="affected-systems" href="#affected-systems" class="anchor"> </a> Affected Systems </h2> <ul> <li>CKEditor 5 (ckeditor5 npm package)</li> <li>CKEditor 5 Engine (@ckeditor/ckeditor5-engine npm package)</li> <li><strong>ckeditor5</strong>: >= 29.0.0, < 47.7.4 (Fixed in: <code>47.7.4</code>)</li> <li><strong>ckeditor5</strong>: >= 48.0.0, < 48.5.1 (Fixed in: <code>48.5.1</code>)</li> <li><strong>@ckeditor/ckeditor5-engine</strong>: >= 29.0.0, < 47.7.4 (Fixed in: <code>47.7.4</code>)</li> <li><strong>@ckeditor/ckeditor5-engine</strong>: >= 48.0.0, < 48.5.1 (Fixed in: <code>48.5.1</code>)</li> </ul> <h2> <a name="code-analysis" href="#code-analysis" class="anchor"> </a> Code Analysis </h2> <h3> <a name="commit-4d9c5bb" href="#commit-4d9c5bb" class="anchor"> </a> Commit: <a href="https://github.com/ckeditor/ckeditor5/commit/4d9c5bb34f63cd956d15ccafbe584e14280c86a0">4d9c5bb</a> </h3> <p>Internal security fix in ViewDomConverter (v48.5.1) replacing data: URI denylist with strict binary media allowlist and stripping C0 control characters.<br> </p> <div class="highlight"><pre class="highlight diff"><code><span class="gh">diff --git a/packages/ckeditor5-engine/src/view/domconverter.ts b/packages/ckeditor5-engine/src/view/domconverter.ts index a5fc5874ce0..2643d7a9332 100644 </span><span class="gd">--- a/packages/ckeditor5-engine/src/view/domconverter.ts </span><span class="gi">+++ b/packages/ckeditor5-engine/src/view/domconverter.ts </span><span class="p">@@ -291,10 +291,34 @@</span> export class ViewDomConverter { return true; } <span class="err"> </span><span class="gd">- if ( attributeValue.replace( /\s+/g, '' ).match( /^(javascript:|data:(image\/svg|text\/x?html))/i ) ) { </span><span class="gi">+ // eslint-disable-next-line no-control-regex + attributeValue = attributeValue.replace( /[\s\u0000-\u0020]+/g, '' ); + + if ( attributeValue.match( /^javascript:/i ) ) { </span> return false; } <span class="err"> </span><span class="gi">+ 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; + } + } + </span> return true; } </code></pre></div> <p></p> <h3> <a name="commit-a750e38" href="#commit-a750e38" class="anchor"> </a> Commit: <a href="https://github.com/ckeditor/ckeditor5/commit/a750e38635db6a18c5b11599c09f4fd702850423">a750e38</a> </h3> <p>Backport of ViewDomConverter data: URI allowlist and C0 control character stripping to v47.7.4 LTS.</p> <h2> <a name="mitigation-strategies" href="#mitigation-strategies" class="anchor"> </a> Mitigation Strategies </h2> <ul> <li>Upgrade CKEditor 5 packages to versions containing the strict data: URI allowlist and C0 control character normalization.</li> <li>Restrict General HTML Support (GHS) configuration to disallow active document container elements (<object>, <embed>, <iframe>).</li> <li>Enforce Content Security Policy (CSP) directives such as object-src 'none' and restrictive frame-src policies to block unauthorized sub-document execution.</li> </ul> <p><strong>Remediation Steps:</strong></p> <ol> <li>Audit package.json and lockfiles for ckeditor5 and @ckeditor/ckeditor5-engine versions >= 29.0.0.</li> <li>Upgrade installations on the 48.x track to 48.5.1 or later.</li> <li>Upgrade installations on the 47.x LTS track (or earlier >= 29.0.0 versions) to 47.7.4 or later.</li> <li>Review custom GeneralHtmlSupport configurations to ensure attributes on <object>, <embed>, and <iframe> are not overly permissive.</li> <li>Verify that server-side HTML sanitizers processing CKEditor output also enforce an allowlist for data: URI MIME types and strip ASCII C0 control characters (0x00-0x20).</li> </ol> <h2> <a name="references" href="#references" class="anchor"> </a> References </h2> <ul> <li><a href="https://www.cve.org/CVERecord?id=CVE-2026-116687">CVE-2026-116687 Official CVE Record</a></li> <li><a href="https://github.com/ckeditor/ckeditor5/security/advisories/GHSA-v6mg-96c6-gmpq">GitHub Security Advisory GHSA-v6mg-96c6-gmpq</a></li> <li><a href="https://github.com/ckeditor/ckeditor5/commit/4d9c5bb34f63cd956d15ccafbe584e14280c86a0">CKEditor 5 Patch Commit (v48.5.1)</a></li> <li><a href="https://github.com/ckeditor/ckeditor5/commit/a750e38635db6a18c5b11599c09f4fd702850423">CKEditor 5 LTS Patch Commit (v47.7.4)</a></li> <li><a href="https://github.com/ckeditor/ckeditor5/releases/tag/v48.5.1">CKEditor 5 v48.5.1 Release Tag</a></li> <li><a href="https://github.com/ckeditor/ckeditor5/releases/tag/v47.7.4">CKEditor 5 v47.7.4 Release Tag</a></li> <li><a href="https://ckeditor.com/docs/ckeditor5/latest/features/html/general-html-support.html">CKEditor 5 Documentation: General HTML Support</a></li> </ul> <hr> <p><em><a href="https://cvereports.com/reports/CVE-2026-116687">Read the full report for CVE-2026-116687 on our website</a> for more details including interactive diagrams and full exploit analysis.</em></p>
Top comments (0)