
DOMPurify v3.4.13
DOMPurify —— 一个仅基于 DOM、超快、高容错的 XSS 过滤器,适用于 HTML、MathML 和 SVG。DOMPurify 默认安全,但提供大量可配置项和钩子。演示:
DOMPurify
DOMPurify 是一款仅依赖 DOM、速度极快且极其宽容的 XSS 净化器,适用于 HTML、MathML 和 SVG。
它也非常简单易用、易于上手。DOMPurify 始于 2014 年 2 月,如今已发展到 v3.4.17 版本。
DOMPurify 以 JavaScript 运行,适用于所有现代浏览器(Safari(10+)、Opera(15+)、Edge、Firefox 和 Chrome——以及几乎所有使用 Blink、Gecko 或 WebKit 的其他环境)。它在 MSIE 或其他旧版浏览器上不会出错,只是什么都不做。
请注意,DOMPurify v2.5.9 是最后一个支持 MSIE 的版本。如需与 MSIE 兼容的重要安全更新,请使用 2.x 分支。
我们的自动化测试在每次推送时都会覆盖当前引擎(Ubuntu、macOS 和 Windows 上的 Chromium、Firefox 和 WebKit)上的 9 种浏览器/操作系统组合,另有一个独立的矩阵会在较旧的引擎快照(大致回溯到 Chromium 110、Firefox 108 和 WebKit 16.4,约三年前)上重新运行整套测试,以便也能捕获过时浏览器上的回归问题。我们还在 jsdom 上使用 Node.js v20、v22、v24、v25 和 v26 运行 DOMPurify。已知较旧的 Node 版本也能正常工作,但嘿……不作保证。
DOMPurify 由在 Web 攻击和 XSS 方面拥有深厚背景的安全人员编写。无需担心。更多详情,请阅读我们的安全目标与威胁模型。请务必阅读。真的。如果你喜欢那些血腥细节,攻击类别与绕过历史页面记录了 DOMPurify 所防御的解析器变异、命名空间、覆盖(clobbering)和模板技巧。
DOMPurify 项目启发了 HTML Sanitizer API 的创建,该 API 已在许多浏览器中发布。同样的能力现正直接在 WHATWG HTML 规范中标准化。
目录
- 它做什么?
- 我如何使用它?
- 有演示吗?
- 如果我发现了 安全 漏洞怎么办?
- 能给我一些净化示例吗?
- 支持哪些内容?
- 像 Internet Explorer 这样的旧版浏览器怎么办?
- DOMPurify 和 Trusted Types 怎么办?
- 我可以配置 DOMPurify 吗?
- 持久化配置
- 钩子
- 已移除的配置
- 持续集成
- 安全邮件列表
- 谁做出了贡献?
它做什么?
DOMPurify 净化 HTML 并防止 XSS 攻击。你可以向 DOMPurify 传入例如一个充满脏 HTML 的字符串,它会返回一个(除非另有配置)包含干净 HTML 的字符串。DOMPurify 会剥离所有包含危险 HTML 的内容,从而防止 XSS 攻击和其他恶意行为。它还快得惊人。我们利用浏览器提供的技术,将它们转化为 XSS 过滤器。你的浏览器越快,DOMPurify 就越快。
我如何使用它?
很简单。只需在你的网站上引入 DOMPurify。
使用未压缩版本(提供 source-map)
<script type="text/javascript" src="dist/purify.js"></script>
使用经过压缩和测试的生产版本(提供 source-map)
<script type="text/javascript" src="dist/purify.min.js"></script>
之后,你可以通过执行以下代码来清理字符串:
const clean = DOMPurify.sanitize(dirty);
或者,如果你喜欢使用 Angular 或类似框架,也可以试试这个:
import DOMPurify from 'dompurify';
const clean = DOMPurify.sanitize('<b>hello there</b>');
生成的 HTML 可以使用 innerHTML 写入 DOM 元素,或使用 document.write() 写入 DOM。这完全由你决定。
请注意,默认情况下,我们允许 HTML、SVG 和 MathML。如果你只需要 HTML(这可能是一个非常常见的用例),你也可以轻松地进行相应配置:
const clean = DOMPurify.sanitize(dirty, { USE_PROFILES: { html: true } });
是否存在潜在隐患?
请注意,如果你_先_对 HTML 进行净化,_然后_再对其进行修改,你很容易使净化的效果失效。如果你在净化_之后_将净化后的标记交给另一个库处理,请务必确认该库不会自行对 HTML 进行改动。有关安全使用的配方以及值得三思的标签/属性,请参阅安全目标与威胁模型;有关后处理和更改标记上下文为何会破坏净化的原因,请参阅攻击类别与绕过历史。
传入 DOM 节点而不是字符串会怎样?
DOMPurify.sanitize() 也接受 DOM 节点(Element、DocumentFragment 或 Document)。自 3.4.14 起,对于并非由 HTML 解析器生成的节点,该路径已得到加固:通过 DOM API 构建或以 XML/XHTML 解析的节点(例如通过 DOMParser 配合 application/xhtml+xml 和 importNode())可能携带保留大小写的属性名,如 ONERROR,或者像 <style> 这样的原始文本元素,其文本中包含元素子节点或自身的结束标签。这两种形态对字符串净化器来说都是不可见的,因为 HTML 解析器永远无法构建它们,但它们在重新解析时会突破出来。DOMPurify 现在按其精确的 Attr 节点移除属性,并将这些字面文本树视为不安全,因此输入侧混合文档上下文的情况已被覆盖。在_输出_侧不混合上下文仍然是你的责任,请参阅上一段。
好的,有道理,我们继续
净化标记之后,你还可以查看 DOMPurify.removed 属性,了解哪些元素和属性被剔除了。请不要使用该属性做出任何安全关键决策。这只是一个满足好奇心的辅助工具。
在服务器上运行 DOMPurify
从技术上讲,DOMPurify 也可以在服务器端配合 Node.js 运行。我们的支持工作力求遵循 Node.js 发布周期。
在服务器上运行 DOMPurify 需要存在 DOM,这大概并不令人意外。通常,jsdom 是首选工具,我们强烈建议使用最新版本的 jsdom。
为什么?因为已知旧版本的 jsdom 存在缺陷,会导致 XSS,即使 DOMPurify 100% 正确执行所有操作。例如,jsdom v19.0.0 中存在已知攻击向量,这些在 jsdom v20.0.0 中已修复——因此我们真的建议保持 jsdom 为最新版本。
另请注意,虽然存在 happy-dom 之类的工具,但目前不被视为安全。目前不建议将 DOMPurify 与 happy-dom 结合使用,这很可能导致 XSS。有关你所选择的服务器端 DOM 为何属于可信计算基的一部分的背景信息,请参阅攻击类别与绕过历史。
在 jsdom 无法运行的运行时上,例如 Cloudflare Workers 或 Vercel Edge,purify-edge 是一个第三方项目,它在基于 parse5 的 window 上运行未经修改的 DOMPurify。我们的测试套件可以通过 npm run test:purify-edge 对其运行,作为兼容性检查。它不由我们维护,测试通过既不代表认可,也不构成安全保证。
除此之外,你完全可以在服务器上使用 DOMPurify。大概吧。这实际上取决于 jsdom 或你在服务器端使用的任何 DOM。如果你能接受这一点,以下就是让它工作的方法:
npm install dompurify
npm install jsdom
对于 jsdom(请使用最新版本),以下代码应该可以解决问题:
const createDOMPurify = require('dompurify');
const { JSDOM } = require('jsdom');
const window = new JSDOM('').window;
const DOMPurify = createDOMPurify(window);
const clean = DOMPurify.sanitize('<b>hello there</b>');
或者,如果你更喜欢使用导入,也可以这样:
import { JSDOM } from 'jsdom';
import DOMPurify from 'dompurify';
const window = new JSDOM('').window;
const purify = DOMPurify(window);
const clean = purify.sanitize('<b>hello there</b>');
如果你在特定环境中遇到无法正常运行的问题,可以参考出色的 isomorphic-dompurify 项目,它解决了人们可能遇到的许多问题。
npm install isomorphic-dompurify
import DOMPurify from 'isomorphic-dompurify';
const clean = DOMPurify.sanitize('<s>hello</s>');
有演示吗?
当然有演示!试用 DOMPurify
如果我发现了安全漏洞怎么办?
首先,请立即通过电子邮件联系我们,以便我们着手修复。PGP 密钥
此外,你很可能符合漏洞赏金的条件!Fastmail 的优秀团队在其服务中使用了 DOMPurify,并将我们的库纳入了他们的漏洞赏金范围。因此,如果你找到了绕过或削弱 DOMPurify 的方法,也请查看他们的网站和漏洞赏金信息。
请给一些净化示例?
净化后的标记是什么样的?嗯,演示展示了一大堆恶意元素的效果。不过,我们也来展示一些更小的示例吧!