DOMPurify最可靠,因其基于真实DOM解析重建后按白名单逐节点裁剪,可防御onerror、javascript:、data:text/html等XSS载荷,避免正则过滤的嵌套绕过、编码混淆与大小写变异问题。

用 DOMPurify 清理 HTML 属性最可靠
直接手写正则或遍历删属性容易漏掉嵌套、编码绕过、大小写变异等问题,DOMPurify 是目前被广泛验证过的白名单方案。它不依赖正则匹配标签名,而是真正解析成 DOM 树再过滤,能防御 onerror、javascript:、data:text/html 等常见 XSS 载荷。
安装后只需一行调用:
const clean = DOMPurify.sanitize(dirtyHTML, {
ALLOWED_ATTR: ['class', 'id', 'src', 'href', 'alt', 'title'],
ALLOWED_TAGS: ['p', 'br', 'strong', 'em', 'a', 'img']
});-
ALLOWED_ATTR是核心白名单,没列进去的属性(比如onclick、style、data-*)默认全清 - 想保留部分
data-属性?得显式写成'data-id'、'data-type',通配符'data-*'不生效 - 如果源 HTML 含有自定义元素(如
<my-card></my-card>),需把它们加进ALLOWED_TAGS,否则整标签会被移除
为什么不能用 innerHTML + 正则删属性
有人试过先塞进 div.innerHTML 再用 replace(/ (on\w+|style|javascript:)/gi, ''),这会出问题:
- HTML 解析阶段已触发事件绑定(比如
<img src="x" onerror="alert(1)" alt="HTML怎么设置白名单批量清理属性" >在设innerHTML时就执行了) - 属性值里的引号闭合可被绕过:
<a href="javascript:alert(1)" onclick="" alert></a>,正则很难全覆盖 -
style属性里藏 CSS 表达式(IE)或url(javascript:...),单纯删style属性还不够,得进值里再扫一遍
需要保留 style 但只允许可信 CSS 怎么办
DOMPurify 支持对 style 做子级白名单控制,靠 CUSTOM_STYLE_HANDLERS 和 FORBID_TAGS 配合:
立即学习“前端免费学习笔记(深入)”;
DOMPurify.addHook('uponSanitizeAttribute', function(node, data) {
if (data.attrName === 'style' && node.tagName === 'SPAN') {
const validProps = new Set(['color', 'font-size', 'text-align']);
const styles = data.attrValue.split(';').map(s => s.trim()).filter(Boolean);
const cleaned = styles
.map(s => {
const [prop] = s.split(':');
return validProps.has(prop.trim()) ? s : '';
})
.filter(Boolean)
.join(';');
node.setAttribute('style', cleaned);
}
});- 这个 hook 在每个属性处理前触发,
node是当前 DOM 节点,data含attrName和attrValue - 不要在 hook 里改
node.parentNode或调removeChild,可能破坏内部遍历逻辑 - 若要全局限制
style,建议直接启用USE_PROFILES: { html: true },它会自动禁用危险 CSS 函数
服务端 Node.js 环境下怎么用
浏览器版 DOMPurify 依赖 DOM API,Node 里得换 jsdom 搭配:
const { JSDOM } = require('jsdom');
const createDOMPurify = require('dompurify');
const window = new JSDOM('').window;
const DOMPurify = createDOMPurify(window);- 必须传入真实
window对象,传{}或空对象会导致sanitize返回空字符串 - 每次调用前不用重复初始化
DOMPurify,它可复用 - 如果 HTML 片段含
<script></script>,默认会被清掉;要保留且执行?别这么干——这是严重安全隐患
真正难的不是加白名单,而是确认哪些属性在你的业务上下文里“可信”。比如 href 允许 mailto: 但不该放 javascript:,src 接受相对路径和 https:,但拒绝 blob: 和 data:——这些规则得贴着你自己的数据来源和渲染逻辑来定,没法通用。



















