HTML 已经转义,为何仍有 XSS?Sharp srcdoc 漏洞中的第二次解析

HTML 已经转义,为何仍有 XSS?Sharp srcdoc 漏洞中的第二次解析

一、背景与趋势

富文本编辑器需要保留链接、媒体和嵌入内容,安全规则因此从"允许哪些标签"扩展到"允许哪些属性及其语义"。某些属性容纳的是 URL,有些是 CSS,还有些直接容纳完整文档。若统一按文本处理,编码层面的正确性也可能掩盖上下文错误。

已确认事实: Sharp 官方公告于 2026-06-24 披露,GitHub 已审核记录于 2026-09-25收录。本期解读的是新收录记录,不是新发生的攻击。

项目 已确认内容
包 Composer 的 code16/sharp,不是 Node.js 图片库 sharp
标识 CVE-2026-61823 / GHSA-qxg3-46rw-79j8
受影响 <9.22.5
最低修复 9.22.5
前提 可编辑 Editor 字段,并有其他用户查看内容

二、技术原理:编码后的属性仍会成为文档

公告确认,富文本处理允许 iframe 的 srcdoc 属性。浏览器在处理属性时会解码实体,再把其中的内容作为子文档解析。于是,对外层属性所做的转义,并未消除内层文档的执行语义。

**工程分析:**安全审计需要追踪数据最终进入什么解释器。字符串第一次输出时是属性值,下一步可能成为 HTML;某一层的安全编码,不能自动继承到下一层。类似原则也适用于模板生成 JavaScript、配置生成命令和数据生成查询,但这些只是工程类比,不是本漏洞的额外攻击链。

官方提交 ec509a2从 iframe 属性白名单移除 srcdoc,并增加对应测试。该提交还处理了其他富文本判断逻辑;本文只围绕 srcdoc 这一项,不把同提交的全部变更都算作这个漏洞的根因。

三、安全实验:不用 JavaScript 也能看懂问题

以下 Python 示例仅处理字符串与字典,不启动浏览器。用普通段落代替任何脚本,观察"属性安全编码"和"内层内容仍是 HTML"可以同时成立。

python 复制代码
from html import escape, unescape

inner = "<p>仅供演示的文字</p>"
attribute_text = escape(inner, quote=True)
assert "<p>" not in attribute_text
assert unescape(attribute_text) == inner

# 教学用结构化属性筛选,不是生产 HTML 消毒器。
def keep_attributes(attrs):
    allowed = {"title", "width", "height"}
    return {k: v for k, v in attrs.items() if k in allowed}

result = keep_attributes({"srcdoc": inner, "title": "demo"})
assert "srcdoc" not in result
assert result == {"title": "demo"}
print("nested interpretation checks passed")

生产环境不能用这段字典函数替代成熟消毒器,因为真实 HTML 包含大小写、命名空间、解析修复和多种编码。示例只证明一条设计原则:不需要内嵌文档能力时,删除这个能力入口比继续尝试给它"多转义一次"更容易验证。

四、影响范围与证据边界

存储型 XSS 的危险在于写入与触发分离:低权限编辑者提交内容,另一个身份稍后查看。**工程推断:**若查看者拥有高权限,可能扩大浏览器内可执行操作的影响;但实际可访问数据取决于同源环境、iframe sandbox、Cookie 属性和应用授权。

因此,不能把 XSS 直接等同于"所有管理员 Cookie 必然泄露",更不能写成服务器远程代码执行。HttpOnly 可以限制脚本读取特定 Cookie,却不证明整个页面免受脚本影响。不同防线各自保护不同对象。

五、开发与安全团队如何修复

**立即升级:**核对 composer.lock 与运行环境中的实际包,升级到至少 9.22.5 的兼容修复版本;不要把 npm 的同名包升级当作处置完成。

**治理历史内容:**升级输入消毒流程不一定自动改写数据库里的旧内容。先确定系统在写入、读取还是渲染阶段应用消毒,再在备份上盘点历史富文本。采用解析器进行迁移,验证页面展示与权限流程,避免用正则大范围破坏合法内容。

**建立上下文测试:**对每个允许属性记录其语义和必要性。测试既要断言危险属性已被移除,也要确保正常段落、链接和允许的媒体仍然存在。测试必须覆盖预览页、详情页、管理页和导出路径,而不是只检查编辑器提交接口。

**降低后果:**将低信任富文本与敏感管理操作隔离;按业务需要部署 CSP 和严格的嵌入策略。它们是纵深防护,不能替代库升级和正确消毒。日志只记录内容标识与变更主体,避免复制完整敏感正文。

六、总结

"已经转义"必须补全后半句:针对哪一个解释上下文?Sharp 的案例提醒我们,把富文本属性当作能力集合审查,比笼统地认为"所有输入都已清洗"更可靠。

相关推荐
剪刀石头布啊3 小时前
vue-react为何要虚拟dom
前端
剪刀石头布啊3 小时前
ahooks常用的一些库,我们使用一下
前端
剪刀石头布啊3 小时前
从git更新本地提交记录到更新已经推送到远端记录
前端
Flynt5 小时前
axios 被投毒半年后,我把 npm 的"安全防线"实测了一遍:最信任的 SHA512 是安慰剂
前端·npm·node.js
excel6 小时前
Base62 和 Base64 有什么区别?
前端
风骏时光牛马7 小时前
大模型底层架构与AI源码深度剖析
前端
掘金挖土8 小时前
前端手摸手跑路之 AI 应用开发(九)
前端·后端
中文呀11 小时前
三维 GIS 离线缓存实战:逆向 CesiumOfflineCache,并亲手为它补上"自动更新"能力
前端
前进前进前进11 小时前
TRAE 全链路实战:做了一个警示牌一键生成器:纯 Canvas、单文件、零依赖
前端