加了sandbox属性不等于安全,而是默认全锁死:JS不执行、表单点不动、localStorage读不到、window.open()静默失败;必须显式添加allow-scripts等白名单token才能恢复对应能力,且每个token都增加攻击面,需按最小权限原则精确配置。

加了 sandbox 属性不等于安全,而是默认全锁死:JS 不执行、表单点不动、localStorage 读不到、window.open() 静默失败——必须显式加白名单 token 才能干活。
为什么写了 sandbox 却白屏或脚本不运行
因为 sandbox 或 sandbox="" 等价于启用全部限制。浏览器不是“加载失败”,而是底层拦截整个响应体,Network 面板可能显示 net::ERR_BLOCKED_BY_RESPONSE;控制台也不报错,只是静默丢弃所有主动行为。
- 写
<iframe sandbox src="widget.html"></iframe>→ 连alert(1)都不会弹 - 在控制台执行
document.querySelector('iframe').sandbox,返回空DOMTokenList []就说明没开任何权限 - 常见误判是怀疑路径错、JS 写错、CORS 问题——其实只需先加
allow-scripts
allow-scripts 是最常加也最容易误判的权限
allow-scripts 只解禁外链脚本加载与执行(<script src="xxx.js"></script> 和 eval()),但它不恢复 HTML 解析阶段的内联能力:
-
onclick="doX()"、onload、javascript:void(0)全部失效,且不报错 -
document.write()、同步XMLHttpRequest、new Function()仍被禁止 - iframe 的
window.origin强制变为"null",window.parent和document依然不可访问 - 必须改用
addEventListener绑定事件,不能依赖内联写法
哪些组合可用,哪些绝对要避开
按最小权限配,拒绝堆砌。每个 token 都意味着额外攻击面:
立即学习“前端免费学习笔记(深入)”;
- 只展示带 JS 的广告/图表:
sandbox="allow-scripts allow-popups"(禁表单、禁存储、禁跳转父页) - 嵌入用户填写的问卷(需提交):
sandbox="allow-scripts allow-forms allow-popups"(表单走 CORS 提交,不碰allow-same-origin) - 加载同源可信子系统(如
https://yourapp.com/admin.html):sandbox="allow-scripts allow-same-origin allow-forms"(必须确认 URL 真同源,且服务端返回正确 CORS 头) - 绝对不要写:
sandbox="allow-scripts allow-same-origin allow-popups allow-forms allow-top-navigation"——这和没加sandbox几乎一样危险
动态插入 iframe 或使用 srcdoc 时的坑
sandbox 对动态创建和内联内容同样生效,但容易被忽略:
- React/Vue 中用
dangerouslySetInnerHTML插入 iframe?必须在插入前就写死sandbox属性值,iframe.sandbox = "allow-scripts"动态赋值无效 -
srcdoc内容哪怕没网络请求,也受sandbox限制;onclick同样静默失效 - 子页来自
about:blank或动态写入时,event.origin是"null",比对时不能只用includes(),得严格相等 - 销毁 iframe 前必须显式调用
iframe.contentWindow?.close(),否则 setInterval、WebSocket、message 监听器继续后台运行,无法 GC
真正麻烦的不是怎么加权限,而是权限开了之后你以为能做的事其实还是被拦着——比如 allow-same-origin 加了却读不到 localStorage,往往是因为 src 并不同源;又比如 postMessage 发出去没人收,其实是父页监听时用了 '*' 而不是具体 origin。这些边界细节,才是线上出问题最多的地方。



















