dompurify配置必须禁用add_tags和add_attr,仅用allowed_tags/attr声明最小白名单;若需svg须启用safe_for_templates:true,且服务端须用jsoup等独立方案二次校验。

DOMPurify 配置必须禁用 ADD_TAGS 和 ADD_ATTR
很多人为了“支持更多富文本样式”,在 DOMPurify.sanitize() 里加 ADD_TAGS: ['svg', 'math'] 或 ADD_ATTR: ['data-src', 'loading'],结果引入了执行通道。SVG 中的 <g onload="..."></g>、MathML 中的 <annotation-xml encoding="text/html"></annotation-xml> 都能绕过默认过滤。
正确做法是:只用 ALLOWED_TAGS 和 ALLOWED_ATTR 显式声明最小集合;若真需 SVG,必须同时启用 SAFE_FOR_TEMPLATES: true,否则内联 onload 会逃逸。
-
FORBID_TAGS: ['script', 'iframe', 'frame', 'frameset']和FORBID_ATTR: ['onerror', 'onclick', 'javascript:', 'data:text/html']是双重保险,不能省 - 不要依赖
WHOLE_DOCUMENT: false就以为安全——它只控制是否解析完整 HTML 文档,不改变属性扫描逻辑 - 服务端复用同一份 DOMPurify 配置是危险的:前端可被禁用 JS 或篡改配置,服务端必须用独立实现(如 Java 的 jsoup Cleaner)做二次校验
jsoup Cleaner 白名单必须基于业务最小集构造
Java 场景下,用 Whitelist.relaxed() 看似省事,实则等同于放行全部 img 标签及其所有属性,包括 img[src] onerror="fetch(...)" 这种组合。
真正安全的写法是逐标签限定属性,例如:
Whitelist whitelist = new Whitelist();
whitelist.addTags("p", "br", "img", "a");
whitelist.addAttributes("img", "src", "alt", "width", "height");
whitelist.addAttributes("a", "href", "title");
whitelist.addProtocols("a", "href", "http", "https");
- 禁止用正则替换
<script.>[\s\S]*?</script.>—— 对<script></script>大写变体、CDATA 区块、注释包裹的 script 全无效 - jsoup 的
Cleaner必须配合Document.parse()先做语法树构建,再按白名单裁剪,不能跳过解析直接字符串处理 - 自定义
TagNodeVisitor可用于检测 CSS 表达式或url(javascript:...),但需注意性能开销,建议仅对高风险字段启用
正则预处理只能作为兜底,不能替代语义解析
当环境不允许引入完整 HTML 解析器(如嵌入式设备、超轻量前端模块),正则可快速剥离明显危险模式,但必须清楚它的边界:
-
<script>]*>[\s\S]*?</script>无法匹配换行符未转义的模板字符串,也抓不到注释中<!-- <script>alert(1)</script> --> -
on\w+\s*=\s*["'][^"']*["']会漏掉空格变形写法,如onclick=...或 Unicode 编码绕过 - 必须叠加协议检查:
href\s*=\s*["'](?:javascript|vbscript|data):,且要区分大小写(JAVASCRIPT:仍需拦截) - 正则后必须接语义校验:比如提取所有
href值,用URL构造函数尝试解析,捕获异常 URL 即视为可疑
服务端二次校验不能复用前端净化逻辑
前端用 DOMPurify、服务端用同一套 JS 引擎跑相同配置,看似一致,实则埋雷:一旦 DOMPurify 某个小版本修复了某个绕过漏洞,而服务端未同步升级,攻击者就能利用时间差注入 payload。
更稳妥的做法是语言隔离 + 逻辑隔离:
- 前端用 DOMPurify(浏览器环境最优),服务端用 jsoup(JVM 环境最优)或 html5lib(Python 环境最优),各自维护独立更新节奏
- 服务端校验应额外检查上下文敏感点:CSS 中的
expression(...)(IE)、url("javascript:...")、background-image中的 data URI - 对用户提交的 HTML,服务端应记录原始字符串与两次净化后的 diff,便于事后审计绕过路径
真正难的不是写一个“看起来能删 script 标签”的函数,而是覆盖所有隐式执行路径——属性值里的 JS、CSS 里的 URL、HTML 注释里的伪装、甚至 base64 编码的 data URI。工具链越长,各环节的语义一致性越关键,任何一处松动都可能让整条防线失效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











