加 sandbox 后白屏、JS 不执行、按钮失效,因 sandbox 是白名单机制,默认启用全部限制;必须显式添加 allow-scripts 等权限,且需在插入 DOM 前以字符串形式设置。

为什么加了 sandbox 却白屏、JS 不执行、按钮点不动
因为 sandbox 是白名单机制,不是“开关”。写成 <iframe sandbox> 或 <iframe sandbox=""> 就等于启用全部限制:脚本不解析、onclick 静默失效、fetch() 直接报 net::ERR_BLOCKED_BY_RESPONSE、表单提交无响应——浏览器连 HTML 都不进入 DOM 构建流程,更不会报错提示。
验证是否锁死很简单:document.querySelector('iframe').sandbox.length === 0 返回 true 就说明没开任何权限。
-
allow-scripts是绝大多数第三方内容的最低要求;没它,<script src="xxx.js"></script>不加载,alert(1)不弹,fetch()直接失败 - 内联事件(如
onclick="doX()"、javascript:void(0))即使加了allow-scripts也仍被屏蔽,必须改用addEventListener - 动态设置
iframe.sandbox = "allow-scripts"在 Chrome/Firefox 中无效;只在插入 DOM 前用字符串写死才生效
sandbox="allow-scripts allow-same-origin" 到底能不能用
这个组合在生产环境里基本不该出现。它只在 iframe 的 src 与父页协议+域名+端口完全一致时才部分生效;跨域时浏览器静默忽略 allow-same-origin,且不报错——你既得不到 localStorage 或 cookie 访问权,又暴露了配置疏漏。
即使同源 + 这两个 token,iframe 仍无法访问父页 DOM(window.parent、parent.document 依然被拒绝),这是 sandbox 的硬隔离,不可绕过。
立即学习“前端免费学习笔记(深入)”;
-
allow-same-origin和allow-scripts同时存在且 src 真同源 → 等价于大幅削弱沙箱,接近无防护 - 它不影响
postMessage,但通信仍需严格校验event.origin,不能依赖它跳过验证 - SPA 中嵌入用户生成内容、广告位、报表组件等第三方模块时,永远不要加
allow-same-origin
按真实场景配最小权限组合
每个 allow- token 都是攻击面,堆砌等于放弃防护。别抄模板,看需求配:
- 只渲染带交互图表(如 ECharts、Chart.js):
sandbox="allow-scripts allow-popups"。弹窗用于缩放/导出,禁表单、禁 storage、禁跳转 - 嵌入用户提交的富文本预览(含
<form>):sandbox="allow-scripts allow-forms"。提交走 CORS 到后端,禁allow-same-origin避免 cookie 泄露 - 同源子系统入口(如
https://app.example.com/admin):sandbox="allow-scripts allow-same-origin allow-forms"。前提是服务端返回正确Access-Control-Allow-Origin和SameSite=Strictcookie 头 - 绝对禁止
allow-top-navigation和除allow-top-navigation-by-user-activation外的跳转权限——SPA 的路由由主应用控制,iframe 不能擅自改top.location
SPA 动态插入 iframe 时容易被忽略的坑
Vue/React 渲染时若用 v-html 或 dangerouslySetInnerHTML 注入 iframe,确保字符串中 sandbox 属性已存在且值正确——框架不会帮你补,也不会警告。
SPA 路由切换后动态插入的 iframe,sandbox 必须写在 HTML 字符串里或用 setAttribute('sandbox', 'allow-scripts') 设置;直接赋值 iframe.sandbox = 'allow-scripts' 无效。
-
srcdoc内容同样受sandbox限制,哪怕没网络请求,JS 也得靠allow-scripts才能跑 - iframe 生命周期不随 SPA 路由自动回收;不手动清理就会内存泄漏——销毁前必须显式调用
iframe.contentWindow?.close(),再移除 DOM 节点 -
postMessage是唯一合规通信路径,但targetOrigin写成'*'是高危操作;本地开发也应写死为'http://localhost:3000',而非模糊匹配



















