iframe sandbox:它收窄能力,不是加固

sandbox 属性默认剥夺一切能力,靠 allow-* 逐项放回。弄反方向是常见错误:加上 sandbox 之后脚本全不能跑了,因为那是默认值。

<iframe sandbox> 的语义容易记反:空值是最严格的,它剥夺脚本、表单、同源、弹窗、下载等一切能力,然后由 allow-* 一项项放回来。

<iframe sandbox="" src="/embed/comment.html"></iframe>

这个 iframe 里 JS 不执行、表单不能提交、被当成独立源。适合纯展示内容。

逐项放权

值 放回什么 风险
allow-scripts 执行 JS 配合下一项才危险
allow-same-origin 保留原源,可读 cookie 与 scripts 同用等于没沙箱
allow-forms 提交表单 中
allow-popups 开新窗口 中,可被钓鱼利用
allow-top-navigation 导航顶层页面 高,可劫持整页

最危险的一对

sandbox="allow-scripts allow-same-origin" 在与被嵌入页同源时基本等于没有 sandbox:脚本跑起来,且能访问父页面的 DOM —— 它可以直接删掉 sandbox 属性再重载自己。

正确做法是把嵌入内容放到不同源(独立的子域),此时 allow-same-origin 指的是「子域自己的源」,跨源隔离仍然成立。

不要拿它当 CSP 用

sandbox 管的是这个 iframe 能做什么,CSP 管的是这个文档能加载什么。两者互补,不能互替:

  • 要阻止内联脚本 → CSP script-src
  • 要阻止 iframe 导航父页 → sandbox
  • 要阻止 iframe 发请求 → 只能靠 iframe 内部自己的 CSP

实践建议

嵌入对象 建议配置
第三方评论组件 allow-scripts allow-same-origin allow-popups
视频播放器 allow-scripts allow-same-origin allow-presentation
纯展示文档 ``(空)
用户提交的 HTML 不放 iframe,改为 sanitize + 独立源

最后一条是安全底线:用户提交的 HTML 永远不要用 iframe 加载。同源下的 sandbox 有绕过史,独立源才可靠。

sandbox 是白名单不是黑名单。写下 allow-* 之前先问:这个能力被拿走会怎样?

← 返回文章列表

评论

…