Sanitize HTML

12.22'21

对于未知的 HTML 字符串,如果需要在页面渲染,必须要先过滤(sanitize),以预防 XSS(Cross-site scripting)

目标

假设用户输入了可能执行的脚步,例如 <img onerror="alert(1)" src="abc" />,我们需要能过滤掉 onerror属性。

实现

建立 tag 和 attribute 的白名单,基于输入的 HTML 字符串建立 DOM 树,遍历后生成安全的 HTML 字符串。

那么如何基于 HTML 字符串获得对应的 DOM 树呢?

使用 DOMParser

https://developer.mozilla.org/en-US/docs/Web/API/DOMParser

const parser = new DOMParser()
const doc = parser.parseFromString(htmlString, 'text/html')

遍历和复制

遍历树上每个节点,复制安全的属性到新的树节点

大致的流程

const node = doc.body
const newNode = doc.createElement(node.tagName)

Array.from(node.attributes).forEach(({ name, value }) => {
  // For style
  if (name === 'style') {
    Array.from(node.style).forEach(styleName => {
      // Filter styleName
      newNode.style.setProperty(
        styleName, 
        node.style.getPropertyValue(styleName)
      )
    })
  } else {
    // Filter attribute
    // Check URI attribute
    // ...
    newNode.setAttribute(name, value)
  }
})

// Recursively node.childNodes
📖