Execution of JavaScript code using malformed HTML in ckeditor
Description
ckeditor is an open source WYSIWYG HTML editor with rich content support. A potential vulnerability has been discovered in CKEditor 4 Fake Objects package. The vulnerability allowed to inject malformed Fake Objects HTML, which could result in executing JavaScript code. It affects all users using the CKEditor 4 plugins listed above at version < 4.16.2. The problem has been recognized and patched. The fix will be available in version 4.16.2.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
CKEditor 4 Fake Objects plugin before 4.16.2 allows XSS via malformed HTML, leading to arbitrary JavaScript execution.
Vulnerability
The vulnerability resides in the Fake Objects plugin of CKEditor 4. It allows injection of malformed Fake Objects HTML, which can result in executing JavaScript code. Affected versions are all CKEditor 4 versions prior to 4.16.2. [1][2]
Exploitation
An attacker can craft a malformed Fake Objects HTML element. The vulnerability is triggered when the editor processes the malformed HTML, potentially during content rendering or editing. No special authentication is required if the attacker can supply content to the editor. The exact steps involve inserting a specially crafted fake object element that bypasses sanitization. [3]
Impact
Successful exploitation leads to arbitrary JavaScript execution in the context of the CKEditor instance. This can result in cross-site scripting (XSS), allowing the attacker to steal cookies, perform actions on behalf of the user, or deface the page. The impact is limited to the editor's context but can affect the entire application if the editor is used in a sensitive area. [2]
Mitigation
The fix is available in CKEditor 4 version 4.16.2, released on 2021-08-12. Users should upgrade to 4.16.2 or later. For those unable to upgrade, consider disabling the Fake Objects plugin or applying input sanitization. Note that CKEditor 4 reached end-of-life in June 2023; open-source versions after 4.22.1 no longer receive security updates. Commercial LTS support is available until December 2028. [1][2]
AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
ckeditor4npm | < 4.16.2 | 4.16.2 |
Affected products
2- ckeditor/ckeditor4v5Range: < 4.16.2
Patches
1de3c00154071Merge pull request #49 from cksource/sec/48
3 files changed · +74 −31
plugins/fakeobjects/plugin.js+69 −29 modified@@ -27,30 +27,6 @@ return length2; } - var htmlFilterRules = { - elements: { - $: function( element ) { - var attributes = element.attributes, - realHtml = attributes && attributes[ 'data-cke-realelement' ], - realFragment = realHtml && new CKEDITOR.htmlParser.fragment.fromHtml( decodeURIComponent( realHtml ) ), - realElement = realFragment && realFragment.children[ 0 ]; - - // Width/height in the fake object are subjected to clone into the real element. - if ( realElement && element.attributes[ 'data-cke-resizable' ] ) { - var styles = new cssStyle( element ).rules, - realAttrs = realElement.attributes, - width = styles.width, - height = styles.height; - - width && ( realAttrs.width = replaceCssLength( realAttrs.width, width ) ); - height && ( realAttrs.height = replaceCssLength( realAttrs.height, height ) ); - } - - return realElement; - } - } - }; - CKEDITOR.plugins.add( 'fakeobjects', { // jscs:disable maximumLineLength lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE% @@ -67,7 +43,7 @@ htmlFilter = dataProcessor && dataProcessor.htmlFilter; if ( htmlFilter ) { - htmlFilter.addRules( htmlFilterRules, { + htmlFilter.addRules( createHtmlFilterRules( editor ), { applyToAll: true } ); } @@ -183,17 +159,81 @@ if ( fakeElement.data( 'cke-real-node-type' ) != CKEDITOR.NODE_ELEMENT ) return null; - var element = CKEDITOR.dom.element.createFromHtml( decodeURIComponent( fakeElement.data( 'cke-realelement' ) ), this.document ); + var realElementHtml = decodeURIComponent( fakeElement.data( 'cke-realelement' ) ), + filteredHtml = filterHtml( this, realElementHtml ), + realElement = CKEDITOR.dom.element.createFromHtml( filteredHtml, this.document ); if ( fakeElement.data( 'cke-resizable' ) ) { var width = fakeElement.getStyle( 'width' ), height = fakeElement.getStyle( 'height' ); - width && element.setAttribute( 'width', replaceCssLength( element.getAttribute( 'width' ), width ) ); - height && element.setAttribute( 'height', replaceCssLength( element.getAttribute( 'height' ), height ) ); + width && realElement.setAttribute( 'width', replaceCssLength( realElement.getAttribute( 'width' ), width ) ); + height && realElement.setAttribute( 'height', replaceCssLength( realElement.getAttribute( 'height' ), height ) ); } - return element; + return realElement; }; + function createHtmlFilterRules( editor ) { + return { + elements: { + $: function( element ) { + var attributes = element.attributes, + realHtml = attributes && attributes[ 'data-cke-realelement' ], + filteredRealHtml = filterHtml( editor, decodeURIComponent( realHtml ) ), + realFragment = realHtml && new CKEDITOR.htmlParser.fragment.fromHtml( filteredRealHtml ), + realElement = realFragment && realFragment.children[ 0 ]; + + // Width/height in the fake object are subjected to clone into the real element. + if ( realElement && element.attributes[ 'data-cke-resizable' ] ) { + var styles = new cssStyle( element ).rules, + realAttrs = realElement.attributes, + width = styles.width, + height = styles.height; + + width && ( realAttrs.width = replaceCssLength( realAttrs.width, width ) ); + height && ( realAttrs.height = replaceCssLength( realAttrs.height, height ) ); + } + + return realElement; + } + } + }; + } + + // Content stored inside fake element is raw and should be explicitly + // passed to ACF filter. Additionally some elements can have prefixes in tag names, + // which should be removed before filtering and added after it. + function filterHtml( editor, html ) { + var unprefixedElements = [], + prefixRegex = /^cke:/i, + dataFilter = new CKEDITOR.htmlParser.filter( { + elements: { + '^': function( element ) { + if ( prefixRegex.test( element.name ) ) { + element.name = element.name.replace( prefixRegex, '' ); + + unprefixedElements.push( element ); + } + }, + iframe: function( element ) { + element.children = []; + } + } + } ), + acfFilter = editor.activeFilter, + writer = new CKEDITOR.htmlParser.basicWriter(), + fragment = CKEDITOR.htmlParser.fragment.fromHtml( html ); + + dataFilter.applyTo( fragment ); + acfFilter.applyTo( fragment ); + + CKEDITOR.tools.array.forEach( unprefixedElements, function( element ) { + element.name = 'cke:' + element.name; + } ); + + fragment.writeHtml( writer ); + + return writer.getHtml(); + } } )();
plugins/flash/plugin.js+1 −1 modified@@ -39,7 +39,7 @@ init: function( editor ) { var allowed = 'object[classid,codebase,height,hspace,vspace,width];' + 'param[name,value];' + - 'embed[height,hspace,pluginspage,src,type,vspace,width]'; + 'embed[allowfullscreen,height,hspace,pluginspage,src,type,vspace,width]'; if ( CKEDITOR.dialog.isTabEnabled( editor, 'flash', 'properties' ) ) allowed += ';object[align]; embed[allowscriptaccess,quality,scale,wmode]';
tests/plugins/fakeobjects/fakeobjects.js+4 −1 modified@@ -19,7 +19,10 @@ function fakeHtml( editor, elHtml, className, type ) { bender.editors = { editor: { - name: 'editor1' + name: 'editor1', + config: { + extraAllowedContent: 'em' + } } };
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
13- github.com/advisories/GHSA-m94c-37g6-cjhcghsaADVISORY
- lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/NYA354LJP47KCVJMTUO77ZCX3ZK42G3T/mitrevendor-advisoryx_refsource_FEDORA
- lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/UVOYN2WKDPLKCNILIGEZM236ABQASLGW/mitrevendor-advisoryx_refsource_FEDORA
- lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/WAGNWHFIQAVCP537KFFS2A2GDG66J7XD/mitrevendor-advisoryx_refsource_FEDORA
- nvd.nist.gov/vuln/detail/CVE-2021-37695ghsaADVISORY
- github.com/ckeditor/ckeditor4/commit/de3c001540715f9c3801aaa38a1917de46cfcf58ghsax_refsource_MISCWEB
- github.com/ckeditor/ckeditor4/security/advisories/GHSA-m94c-37g6-cjhcghsax_refsource_CONFIRMWEB
- lists.debian.org/debian-lts-announce/2021/11/msg00007.htmlghsamailing-listx_refsource_MLISTWEB
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/NYA354LJP47KCVJMTUO77ZCX3ZK42G3TghsaWEB
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/UVOYN2WKDPLKCNILIGEZM236ABQASLGWghsaWEB
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/WAGNWHFIQAVCP537KFFS2A2GDG66J7XDghsaWEB
- www.oracle.com/security-alerts/cpujan2022.htmlghsax_refsource_MISCWEB
- www.oracle.com/security-alerts/cpuoct2021.htmlghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.