Sanitizer(给你的DOM消消毒)

大家好,我卡颂。
业务中经常遇到需要处理有风险的DOM的场景,比如:

  • 各种工具的文本粘贴功能
  • 需要渲染服务端返回HTML的场景
为了阻止潜在的XSS攻击,有两个选择:
  • escape(转义)
  • sanitize(消毒)
本文会介绍这两者的区别以及为DOM消毒的API —— Sanitizer
Sanitizer(给你的DOM消消毒)
文章图片

本文内容来自 Safe DOM manipulation with the Sanitizer API
转义与消毒 假设,我们想将这样一段HTML字符串插入DOM
const str = "Sanitizer(给你的DOM消消毒)
文章图片

默认情况下Sanitizer会移除所有可能导致JS执行的代码。
丰富的配置 Sanitizer不仅开箱即用,还提供丰富的白名单、黑名单配置:
const config = { allowElements: [], blockElements: [], dropElements: [], allowAttributes: {}, dropAttributes: {}, allowCustomElements: true, allowComments: true }; new Sanitizer(config)

比如,allowElements定义元素白名单,只有名单内的元素会被保留,与之对应的blockElements是元素黑名单:
const str = `hello world`new Sanitizer().sanitizeFor("div", str) // hello worldnew Sanitizer({allowElements: [ "b" ]}).sanitizeFor("div", str) // hello worldnew Sanitizer({blockElements: [ "b" ]}).sanitizeFor("div", str) // hello worldnew Sanitizer({allowElements: []}).sanitizeFor("div", str) // hello world

allowAttributes是属性白名单,与之对应的dropAttributes是属性黑名单,对于如下配置:
{ allowAttributes: {"style": ["span"]}, dropAttributes: {"id": ["*"]}} }

代表消毒后的HTML
  • 只允许span元素拥有style属性
  • 移除所有元素(*通配符代表所有元素)的id属性
Sanitizer(给你的DOM消消毒)
文章图片

兼容性 这么香的API兼容性怎么样呢:
Sanitizer(给你的DOM消消毒)
文章图片

Sanitizer(给你的DOM消消毒)
文章图片

当前只有在Chrome 93之后,开启试验标识后可使用:
about://flags/#enable-experimental-web-platform-features

虽然原生Sanitizer离稳定还遥遥无期,但你可以使用DOMPurify库实现类似功能。
后记 日常你更倾向使用escape还是sanitize呢?
【Sanitizer(给你的DOM消消毒)】欢迎加入人类高质量前端框架研究群,带飞

    推荐阅读