
sandbox 属性不是“加了就安全”,而是“加了就全锁死”——不显式声明权限,alert()、fetch()、onclick、表单提交、localStorage 全部静默失效,连控制台都不报错。
为什么加了 sandbox 就白屏或脚本不执行
浏览器把 <iframe sandbox></iframe> 当作一个 origin 为 "null" 的全新隔离环境,直接跳过 HTML 解析和脚本执行流程。Network 面板可能显示 net::ERR_BLOCKED_BY_RESPONSE,这不是后端问题,是沙箱在响应体解析阶段就拦截了。
- 验证方法:控制台执行
document.querySelector('iframe').sandbox,返回空DOMTokenList []就说明没开任何权限 -
sandbox=""、sandbox=" "、sandbox(无值)三者完全等效,全部锁死 - 动态设置
iframe.sandbox = "allow-scripts"无效,必须在 DOM 插入前写死属性值 - 哪怕只用
srcdoc内联 HTML,也一样被锁死,不加权限照样不执行 JS
sandbox="allow-scripts" 能做什么、不能做什么
这是最常用也最容易误判的权限项。它只解禁外链脚本加载与执行,其他所有行为仍被硬性屏蔽。
- ✅ 可运行:
<script src="https://trusted.example/widget.js"></script>(需服务端带Access-Control-Allow-Origin) - ❌ 不可运行:
<script>alert(1)</script>(内联 script 静默忽略) - ❌ 不可运行:
<button onclick="fetch('/api')">click</button>(内联事件处理器完全失效) - ❌ 不可运行:
javascript:void(0)、eval()、setTimeout("alert(1)")、Function构造器 - ⚠️ 注意:
allow-scripts不递归授权——外链脚本里再document.write("<script></script>")仍被禁止
哪些 allow-* 组合实际可用,哪些等于关掉沙箱
每个 token 都扩大攻击面,必须按最小权限原则叠加,且注意浏览器是否真正识别该 token。
- 广告/第三方插件推荐组合:
sandbox="allow-scripts allow-popups"(支持跳转落地页,但新开窗口不继承沙箱) - 同源可信子系统(如
https://yourapp.com/admin.html)才可考虑:sandbox="allow-scripts allow-same-origin allow-forms",且必须确认协议+域名+端口全一致 - 绝对避开:
allow-same-origin+allow-scripts用于不同源地址(如https://third-party.com)——token 被浏览器忽略,还暴露配置疏漏 - 绝对避开:
allow-top-navigation(可执行top.location = 'https://phishing.site') - 绝对避开堆砌:
sandbox="allow-scripts allow-same-origin allow-popups allow-forms allow-top-navigation",和没加sandbox几乎一样危险
必须配合的纵深防御措施
sandbox 单独使用远远不够,它只是第一道门,后面还得设岗哨。
-
referrerpolicy="no-referrer":防止 iframe 内请求泄露来源 URL -
loading="lazy":延迟加载非首屏 iframe,减少初始攻击面 - 优先用
srcdoc替代src:对静态内容(如说明卡片),直接内联 HTML,避免外部资源加载风险 - 服务端加
X-Frame-Options: DENY或Content-Security-Policy: frame-ancestors 'none':从源头禁止被他人嵌入,与sandbox形成双向防护 -
postMessage必须校验event.origin:不能依赖allow-same-origin绕过验证,沙箱 iframe 的 origin 永远是"null"
沙箱真正的复杂点不在怎么加权限,而在怎么证明你加得对、加得少、加得必要——每次多加一个 allow-*,都要能说出它对应哪一行业务逻辑、哪个不可替代的用户动作,而不是“先加上,以后再说”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











