产品面试:是否应该采用 HTML Sanitizer API 构建富文本编辑器?
题目与使用场景
SaaS 产品准备支持评论、知识库和模板中的用户富文本。团队希望采用浏览器原生 HTML Sanitizer API,减少自维护过滤规则,但该 API 在部分主流浏览器中仍不可用。请决定是否采用,并说明安全、体验、兼容和运营取舍。
面试官考察什么
- 是否先定义威胁模型、允许的内容能力和服务端信任边界。
- 能否区分
setHTML()、自定义 Sanitizer、setHTMLUnsafe()与 Trusted Types 的职责。 - 是否把浏览器覆盖、降级实现、内容一致性和迁移成本量化。
- 能否用分阶段指标验证 XSS 风险、编辑成功率、性能和回滚能力。
作答前的澄清问题
先确认富文本是否需要链接、图片、表格、嵌入、样式和自定义属性;确认内容是否会被服务端渲染、邮件导出、搜索索引或多端复用。再确认支持的浏览器、现有过滤库、合规要求、攻击面和可接受的功能降级。
30 秒回答框架
我会采用“原生 API 优先、服务端持续校验、能力分级降级”的方案,而不是一次性替换现有过滤器。原生 setHTML() 可按规范移除脚本能力标记,但 API 覆盖有限;不支持时使用经过审计的同等策略。先以评论等低复杂场景灰度,指标包括危险载荷拦截、内容保真、编辑成功率、渲染性能和浏览器分布。服务端仍需独立清洗与输出编码,Trusted Types 作为注入汇点的额外约束。
分步骤深入解答
1. 定义用户价值和威胁模型
用户价值是更稳定地发布可格式化内容;主要风险是将不可信 HTML 送入 DOM 或其他渲染汇点。先建立允许元素、属性、链接协议和媒体来源清单,再决定哪些功能值得承担维护成本。
2. 区分原生 API 的能力
Element.setHTML() 和 Document.parseHTML() 使用安全默认清理;自定义配置可以收紧允许列表。setHTMLUnsafe() 适合需要保留某些特殊结构的场景,但必须配合严格配置和审计。规范要求安全方法不能保留脚本能力标记,不能把 API 当作任意 HTML 的通行证。
3. 评估覆盖和降级
MDN 将 HTML Sanitizer API 标为 Limited availability。通过能力检测选择原生路径或服务端/成熟库路径,并让两条路径共享允许列表、测试样例和版本记录。降级时宁可丢弃高风险能力,也不要为了视觉一致放宽策略。
4. 设计跨端内容契约
服务端保存原始输入与规范化后的安全表示,明确哪个表示用于编辑、预览、邮件、搜索和导出。服务端在每个输出边界重新校验,客户端清理只减少 DOM 注入风险,不能替代服务端授权、存储和渲染策略。
5. 设计灰度和指标
先在单一内容类型和少量租户开启,比较原生与降级路径的拦截结果。核心指标包括危险内容拦截率、误删申诉率、编辑提交成功率、首屏和输入延迟、浏览器覆盖、策略版本一致性和安全事件数。
6. 处理 Trusted Types 和运营流程
对高风险注入汇点启用 Trusted Types 报告或强制模式,要求策略函数输出经过验证的类型。建立规则变更审批、恶意样本回归、内容重处理和紧急回滚流程;不要只依赖浏览器更新来改变安全策略。
高质量示范回答
我会先把决策拆成内容能力、威胁模型和运行环境三张表。HTML Sanitizer API 适合在浏览器侧把不可信 HTML 送入 DOM 前做结构化清理,setHTML() 的安全默认值和 WHATWG 规范减少了脚本能力标记被保留的风险,但 MDN 仍标记其覆盖有限。产品方案采用原生 API 优先、成熟库或服务端策略降级;两条路径共享允许元素、属性、协议和测试样例。服务端保存原始内容与安全表示,在页面、邮件、搜索和导出边界分别校验,客户端清理不承担权限或完整 XSS 防护。先灰度评论场景,按危险载荷拦截、内容保真、提交成功率、性能、浏览器分布和安全事件评估。setHTMLUnsafe() 只在确有结构需求时使用,并配合严格配置、Trusted Types 和人工审计。规则升级可回放历史恶意样本,发现回归时立即切回上一版策略。
常见错误
- 因为是浏览器原生 API 就认为服务端无需清理。
- 只看功能演示,不测不支持浏览器和降级路径的一致性。
- 为保留任意嵌入而放宽
setHTMLUnsafe()配置。 - 用单一“过滤成功率”替代内容保真、误删和安全事件指标。
- 把 Trusted Types 当作清理器,或把清理器当作权限控制。
追问及应对
为什么不直接全面切换原生 API?
浏览器覆盖、内容能力和旧数据迁移仍有不确定性。先灰度并保持可回滚的降级路径,能验证真实浏览器和内容分布。
如何处理原生 API 与服务端规则不一致?
共享版本化允许列表和恶意样本,服务端作为最终边界;客户端发现差异时记录策略版本和内容样本,禁止静默放宽规则。
何时值得开启 Trusted Types 强制模式?
当主要注入汇点已盘点、策略函数和第三方组件完成改造,并在报告模式下观察到低误报后,再逐步切换强制模式。