iframe sandbox默认全禁用:脚本不执行、表单失效、弹窗拦截、localStorage不可读写、window.parent为null;必须显式添加allow-scripts等白名单权限才能逐项启用,且每项均增加安全风险。

iframe sandbox 默认就是“全关”,加了没权限就等于白屏
空字符串 sandbox="" 或不写值,等价于启用最严限制:脚本停摆、表单失效、弹窗拦截、window.parent 为 null、localStorage 不可见。这不是 bug,是设计如此。
常见症状包括:Uncaught DOMException: Blocked a frame with origin ...、按钮点击无响应、alert() 不弹、fetch 直接报错或静默失败。
按需开权限必须显式写全,且注意组合风险:
-
sandbox="allow-scripts"→ 允许 JS 执行,但源仍被强制设为null,无法读父页 DOM 或 Cookie -
sandbox="allow-scripts allow-forms"→ 可提交表单,但提交目标仍受 CORS 控制,不自动获得跨域请求权 -
sandbox="allow-scripts allow-same-origin"→ ⚠️ 高危!仅当src真正同源(协议+域名+端口三者一致)时才生效;不同源时浏览器直接忽略allow-same-origin,但你已暴露配置疏漏
postMessage 是跨域 iframe 唯一合法通信通道
Chrome 126+ 已移除 document.domain,iframe.contentWindow.document 跨域必报错,任何绕过尝试都无效。能用的只有 postMessage,它不是“可选方案”,而是唯一事实标准。
立即学习“前端免费学习笔记(深入)”;
父页发消息前必须等 load 事件,否则 iframe.contentWindow 为 null,调用静默失败:
const frame = document.getElementById('myFrame');
frame.addEventListener('load', () => {
// ✅ 此时 contentWindow 才可靠
frame.contentWindow.postMessage({ type: 'init' }, 'https://widget.example.com');
});
别用 setTimeout 硬等,也别依赖 iframe.onload = fn(易被覆盖);子页加载失败(404/500)时 load 仍会触发,需配合 error 事件兜底。
targetOrigin 和 event.origin 必须严格匹配,不能模糊判断
postMessage 的第二个参数 targetOrigin 不是“可选”,而是安全边界。写成 '*' 就等于放弃校验——钓鱼页、中间人劫持的 iframe、XSS 注入页面都能收到消息,浏览器连错误都不抛,静默投递或静默丢弃。
子页收消息时,只检查 event.data.type === 'play' 或用 event.origin.includes('example.com') 是严重漏洞:
-
https://evil-example.com会被includes('example.com')放行 - 必须用
===严格比对:if (event.origin !== 'https://widget.example.com') return - 若子页有多个部署地址(如灰度
https://staging.example.com+ 正式https://widget.example.com),需显式白名单判断 - 子页重定向后
contentWindow.location.origin会变,不能提前缓存,必须在load回调里实时读取
allow-same-origin 不是信任开关,而是同源确认锁
allow-same-origin 不代表“我信它”,而是“它确实和我同源”。浏览器加载时会校验协议、域名、端口三者是否完全一致,缺一不可。不满足就直接忽略该 token,不报错、不警告、不提示。
典型误用:
- 父页是
https://app.example.com,子页src="https://cdn.example.com/widget.html",硬加allow-same-origin→ 无效,localStorage仍是空的,fetch同源请求照样被拦 - 开发用
http://localhost:3000测试,生产却写成https://app.example.com→ 端口/协议不一致,allow-same-origin失效 - 以为加了
allow-scripts allow-same-origin就能自由操作父页 DOM → 实际上window.parent在 sandbox 下仍为null,DOM 访问仍被隔离,只能靠postMessage
真正需要 DOM 互通的场景,应优先评估是否必须 iframe —— 很多时候用 Web Component 或微前端更可控。iframe 的“沙箱”本质是隔离,不是桥梁;加固的关键,是接受这个前提,然后把 postMessage 用对、用严、用稳。



















