怎样安全渲染不可信的 HTML 邮件:不洗标签,直接上沙箱 iframe
来源:making.close.com — 2021-09-29
📋 概述
Close 最早的核心里就有邮件同步:把销售与客户之间的往来邮件拉到应用里,聚合成一条统一时间线。这要求他们能在网页应用里安全展示邮件,避免朴素渲染不可信 HTML 带来的存储型 XSS。他们 2014 年上线该能力,做法至今不常见:完全在浏览器端把不可信 HTML 邮件安全地渲染进单页应用。作者先排除了几个方向——只显示纯文本不行,很多邮件没有像样的纯文本替代,用户也期待看到排版;而 HTML 消毒库要么依赖正则解析 HTML(众所周知是坏主意),要么只支持极小的白名单标签,无法满足带自定义样式的高级邮件;消毒本身也解决不了「应用样式与邮件样式互相污染」,那正是 iframe 的强项。最终方案是把 iframe 的 srcdoc 属性与 sandbox 属性结合起来:srcdoc 让他们直接把已有 HTML 注入,无需另设端点;sandbox 则是安全模型的心脏,默认禁止一切(包括脚本),再按需放行 allow-popups、allow-popups-to-escape-sandbox 与 allow-same-origin(后者仅用于测量内容高度,在不允许脚本的前提下无害)。另加 CSP script-src 'none' 做第二层,并对不支持 sandbox/srcdoc 的浏览器做特性检测、直接降级为纯文本。
🔑 核心要点
- 核心结论反直觉:不洗 HTML,而是靠 iframe 的 sandbox 属性默认禁止脚本,只按需放行三种能力
- srcdoc 解决了工程麻烦:单页应用前端本就从 REST API 拿到邮件体,可直接注入,无需另建端点或跨域令牌
- allow-same-origin 单独用是无害的,但一旦同时允许 allow-scripts 就会让 sandbox 形同虚设,这是本文最该记住的一条
- 三层防脚本:sandbox、CSP script-src 'none'、以及不支持 sandbox 的浏览器直接拒绝渲染 HTML;作者强调这是为了兜住浏览器个别实现的临时漏洞
- CSS 隔离靠注入一层外层 HTML:给邮件合理默认样式、用 base target=_blank 让链接不在 iframe 内打开、并统一字体与图片最大宽度
- 遗留缺口坦白列出:不做图片代理则受隐私与混合内容警告困扰,未来可能改为 iframe src 或加入服务端解析
💡 金句
Most important: Do not let any JavaScript run.
👍 0
👎 0
← 返回 Lobsters 首页