DOMPurify 清洗后为啥还是能执行 XSS?

宇文慧娜 阅读 44

我用 DOMPurify 处理用户输入的 HTML,但发现某些脚本居然还能执行,是不是我用错了?

比如这段代码:

const dirty = '<img src=x onerror=alert(1)>';
const clean = DOMPurify.sanitize(dirty);
document.getElementById('output').innerHTML = clean;

按理说 onerror 应该被过滤掉才对,但页面一加载弹窗就出来了,这正常吗?

我来解答 赞 18 收藏
二维码
手机扫码查看
2 条解答
FSD-洋洋
啊这个情况我遇到过,DOMPurify默认配置确实可能会漏掉一些XSS。问题出在默认情况下它允许onerror这种属性存在。

安全建议是加上严格配置参数:
const clean = DOMPurify.sanitize(dirty, {
FORBID_TAGS: ['img'],
FORBID_ATTR: ['onerror']
});


其实更保险的做法是直接禁用所有内联事件处理:
const clean = DOMPurify.sanitize(dirty, {
ADD_ATTR: ['target'],
ADD_TAGS: ['iframe'],
FORBID_ATTR: ['on*'] // 禁止所有on开头的属性
});


顺便吐槽下,前端安全真是防不胜防,上周我还在和这种注入问题搏斗到凌晨3点... 建议做完处理后用类似console.log(clean)检查下输出内容,确认没有残留的危险属性。

另外记得永远不要直接信任前端验证,后端必须再做一次清洗。
点赞
2026-03-05 23:09
爱学习的诗诗
应该是你没传配置对象进去,DOMPurify 默认只对 HTML 字符串做基础清洗,但如果你的输入是已经解析过的 DOM 节点(比如浏览器自动解析了 HTML 实体),它就不会二次处理。你这段代码里 <img src=x onerror=alert(1)> 实际上会被浏览器当作纯文本,但如果你是用 innerHTML 插入字符串,它会触发 HTML 解析,而 DOMPurify 需要你显式告诉它「这是原始 HTML 字符串」——不过你这段其实没问题,真正的问题是:你是不是在别的地方又把 clean 当作 HTML 再次解析了?比如用 evalnew Function
最可能的原因是你把 cleaninnerHTML 插入后,浏览器又重新解析了一次,而 DOMPurify 只清洗了一次。
修复方案:直接用 textContent 或者确保只插入一次,或者加上 {RETURN_TRUSTED_TYPE: true} 配置避免二次解析:

const dirty = '<img src=x onerror=alert(1)>';
const clean = DOMPurify.sanitize(dirty, {RETURN_TRUSTED_TYPE: true});
document.getElementById('output').innerHTML = clean;
点赞 4
2026-02-25 08:42