资讯动态

CKEditor 4 中数字 ID 导致的编辑器崩溃:14451 缺陷的复现、修复与 CSS 选择器转义原理

发布时间:2026/10/17 2:27:28 来源:尧图企业网站定制
前端UI组件【免费下载链接】ckeditor4The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.项目地址https://gitcode.com/gh_mirrors/ck/ckeditor4点击查看免费下载在 CKEditor 4 中当编辑器内容里存在以数字开头的元素id例如id100时4.5.10 之前的版本在源码模式 ↔ WYSIWYG 模式切换后会抛出选择器语法错误导致工具栏按钮全部失效、编辑器整体不可用。本文以回归测试用例 tests/tickets/14451/1.md 为线索完整还原该缺陷的复现步骤与预期行为并结合 CKEDITOR.tools.escapeCss 与 CKEDITOR.dom.element.find 的源码讲清数字 ID 为什么会让 CSS 选择器非法以及 CKEditor 4 是如何修复它的。缺陷背景#14451 与 CKEditor 4.5.10该问题由社区贡献者 Jakub Chalupa 定位并修复修复记录见 CHANGES.md 中的 CKEditor 4.5.10 版本条目#14451: Fixed: Numeric element ID not escaped properly. Thanks to Jakub Chalupa!回归测试的标签为bender-tags: 4.5.10, bug, trac14451涉及插件为clipboard, contextmenu, toolbar, wysiwygarea, image2, sourcearea——其中image2插件增强图片Enhanced Image是关键触发点因为它的图片说明caption正是figcaption元素。复现场景给figcaption加一个数字 id官方回归测试由两份文件组成用例描述 1.md 和编辑器初始化页面 1.html。初始内容是一个image2插件可识别的图片部件textarea cols80 idclassic nameclassic rows10 figure classimage img altApollo-CSM-LM srchttp://c.cksource.com/a/1/img/demo/apollo-csm-lm.png width200 / figcaptionApollo CMS-LM spacecraft/figcaption /figure /textarea script CKEDITOR.replace( classic, { extraAllowedContent: figcaption[id] } ); /script这里有一处关键配置extraAllowedContent: figcaption[id]CKEditor 的过滤机制默认会移除不被允许的figcaption属性加上这一项才能让id属性在源码模式与 WYSIWYG 模式之间往返时不被过滤掉从而稳定复现缺陷。复现步骤对应 1.md 中的 Scenario切换到源码模式Source mode给figcaption元素添加id100属性切回 WYSIWYG 模式。预期结果不抛出任何错误按钮正常工作。实际缺陷版本行为抛出各种错误Various errors thrown按钮停止响应——编辑器被渲染成完全不可用的状态。根因分析数字 ID 生成了非法的 CSS 选择器切回 WYSIWYG 模式时image2插件及其依赖的 Widget 系统需要按 CSS 选择器查找部件内部的figcaption等节点。CKEditor 4 的封装方法是 CKEDITOR.dom.element 的 find 与 findOne自 4.3.0 引入其设计目标是在原生querySelectorAll/querySelector之上保证选择器上下文隔离——即只在本元素子树内查找。实现方式是先给当前元素临时挂一个id由createTmpId完成再把选择器改写成以下形式function getContextualizedSelector( element, selector ) { var id CKEDITOR.tools.escapeCss( element.$.id ); return # id selector.split( /,\s*/ ).join( , # id ); }见 core/dom/element.js#L2204-L2207。问题就出在# id这一拼接上按 CSS 语法#后面必须是一个合法的标识符identifier而标识符不允许以数字开头。当元素id为100时生成的选择器是#100 .cke-widget ...这样的字符串querySelector会直接抛出SyntaxError: invalid selector异常向上冒泡后中断了整个模式切换流程工具栏事件绑定也随之失效——这正是测试用例中按钮停止工作、编辑器不可用现象的底层原因。值得注意的是缺陷测试特意选择了编辑器内容里带数字id这一场景getContextualizedSelector转义的是当前元素本身的 id通常是 CKEditor 内部随机生成的 id但同一机制要求所有参与拼接的 id 在 CSS 上合法。修复后find/findOne走escapeCss转义数字 id 会被转成#100→#100的合法写法数字前加反斜杠#100选择器不再非法模式切换恢复平稳。修复实现CKEDITOR.tools.escapeCss修复方案是在 core/tools.js 中新增CKEDITOR.tools.escapeCss()工具函数since 4.5.10其逻辑分为两层/** * Returns an escaped CSS selector. CSS.escape() is used if defined, * leading digit is escaped otherwise. * * since 4.5.10 * param {String} selector A CSS selector to escape. * returns {String} An escaped selector. */ escapeCss: function( selector ) { // Invalid input. if ( !selector ) { return ; } // CSS.escape() can be used. if ( window.CSS CSS.escape ) { return CSS.escape( selector ); } // (#681) return cssEscapeForIE( selector ); },空值防御传入null/undefined/ 空串时直接返回避免在拼接选择器时把null拼进字符串优先使用浏览器原生 API现代浏览器提供标准化的CSS.escape()CSSOM 规范的一部分直接委托给它行为与规范完全一致IE 回退对不支持CSS.escape的环境注释中标注(#681)即低版本 IE走内置 polyfill cssEscapeForIE。该函数是一个按 Unicode 码点逐字符转义的自实现版本源码注释标明它源自开源项目 mathiasbynens 的CSS.escape移植版This is the polyfill for the CSS.escape for IE. (#681)对首字符为数字、含特殊符号的标识符都能产出合法的 CSS 转义序列如100→\31 00。这样getContextualizedSelector 中唯一的调用点CKEDITOR.tools.escapeCss( element.$.id )就保证了拼接出的#id前缀在任何 id 取值下都是合法 CSS 选择器find/findOne不再因用户内容中的数字 id 而抛异常。触发链条与受影响范围从源码结构看完整的触发链条是用户在源码模式下给figcaption加了id100或内容中任何参与选择器查找的元素带数字 id切回 WYSIWYG 模式image2插件按选择器定位部件节点其模板中硬编码了figcaption{captionPlaceholder}/figcaption见 plugins/image2/plugin.js#L14find/findOne将元素 id 拼入 CSS 选择器数字 id 未转义导致querySelector抛SyntaxError异常未被捕获模式切换流程中断工具栏、右键菜单等 UI 事件失效编辑器表现为渲染了但不可用。受影响的不只是image2任何依赖element.find()/element.findOne()的插件widget、placeholder、contextmenu 等在遇到同类内容时都会走同一条路径这也是官方测试用例把clipboard, contextmenu, toolbar, wysiwygarea等插件一并列入bender-ckeditor-plugins标签的原因。对使用者的启示升级建议如果你的内容中可能出现数字开头的id例如从其他系统导入的 HTML、figcaption/figure带数字 id 的富文本请确保 CKEditor 4 版本不低于4.5.10该版本起escapeCss已内置无需额外处理自定义内容过滤若允许用户在内容中保留任意id需像测试用例那样通过extraAllowedContent: figcaption[id]一类的配置显式放行否则属性会被过滤器移除缺陷虽不会触发但你的id也留不住插件开发者注意如果你在自研插件中用element.find()/findOne()CKEditor 4.5.10 已保证上下文 id 的转义但如果你自己拼接选择器例如手写# element.$.id必须自行经过CKEDITOR.tools.escapeCss()处理否则会复现同样的崩溃验证方式可直接运行仓库自带的回归用例 tests/tickets/14451/1.html按 1.md 的三步操作验证无错误抛出、按钮可用的预期结果。小结#14451 是一个典型的用户内容污染内部逻辑缺陷figcaption上的数字id100经find/findOne的选择器上下文拼接后变成非法 CSS 选择器导致模式切换时编辑器整体不可用。CKEditor 4 的修复方式是新增CKEDITOR.tools.escapeCss()优先委托原生CSS.escape()IE 下使用内置 polyfill并在选择器拼接点统一转义元素 id。该案例也提示凡是把外部可控字符串拼进 CSS 选择器、HTML 或 JS 上下文的代码都必须做对应的转义处理。赞分享前端UI组件【免费下载链接】ckeditor4The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.项目地址https://gitcode.com/gh_mirrors/ck/ckeditor4点击查看免费下载相关推荐CKEditor 4 在 ENTER_BR 模式下粘贴内容导致编辑器崩溃3858的复现、根因与修复实战CKEditor 4 在 ENTER_BR 模式下粘贴内容导致编辑器崩溃 3858的复现、根因与修复实战 本指南以 CKEditor 4 仓库中的手动回归测前端UI组件CKEditor 4 中 escapeCss 选择器转义机制与表格单元格 ID 兼容性修复Bug 681深度解析CKEditor 4 中 escapeCss 选择器转义机制与表格单元格 ID 兼容性修复Bug 681深度解析 导读 本文围绕 CKEditor 4 仓库前端UI组件Anytype Android同步功能深度解析跨设备知识管理解决方案Anytype Android同步功能深度解析跨设备知识管理解决方案 Anytype是一款强大的Android客户端专为跨设备知识管理设计其核心功能在于提移动开发上一篇免越狱 iOS 虚拟定位工具3 步完成 iPhone 位置模拟完整指南下一篇免费浏览器音乐解密ncm/qmc/kgm 完整解锁指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑