唯一可靠的方式是用 sandbox 属性禁用 allow-top-navigation,其他 js 拦截手段全部无效;因 top.location.href 跳转是浏览器内核级导航行为,非事件,无法通过 beforeunload、重写 getter 或 postmessage 校验拦截,且 sandbox 必须静态声明于 iframe 标签中才生效。

唯一可靠的方式是用 sandbox 属性禁用 allow-top-navigation,其他 JS 拦截手段全部无效或不可靠。
为什么 window.top.location 无法被 JS 拦截
子页面执行 top.location.href = 'https://evil.com' 是浏览器原生导航行为,不是事件,无法用 beforeunload 或重写 location 属性来阻止。即使你在父页提前覆盖 window.top 的 getter,也只对部分访问生效,且跨域时直接抛 SecurityError,而跳转早已发生。
常见错误包括:
- 在子页加
if (top !== self) top.location = self.location—— 这恰恰是攻击者常用手法,用来防被嵌套,但会反向劫持你的父页 - 监听
message后再跳转 —— 子页根本不需要发消息,它可以直接跳 - 用
document.write或<meta http-equiv="refresh">触发跳转 —— 这些同样绕过 JS 检测
sandbox 属性必须显式关闭 top-navigation 权限
sandbox 是 HTML 层面的内核级隔离机制,加载前就切断能力,不是补丁。关键规则:
- 只要没写
allow-top-navigation(或allow-top-navigation-by-user-activation),top.location写操作就会静默失败或抛SecurityError -
sandbox=""(空值)比不写更安全,它默认禁用所有权限,包括导航、脚本、表单 - 若需运行脚本,只加最小集:
sandbox="allow-scripts allow-same-origin"—— 注意:这里依然不含allow-top-navigation - 移动端更严格:即使没开
allow-popups,点击链接也不会跳父页,只会静默失败
错误配置示例:sandbox="allow-scripts allow-top-navigation" —— 这等于授权子页任意控制你整个标签页。
如何验证 sandbox 是否真正生效
别信文档,动手查:
- 打开开发者工具 → 选中
iframe元素 → 控制台输入document.querySelector('iframe').sandbox,返回的DOMTokenList中不能含allow-top-navigation - 手动在子页 console 执行
top.location.href = 'https://test.com',应报错SecurityError: Blocked a frame from accessing a cross-origin frame(跨域)或静默失败(同源) - 检查 Network 面板里 iframe 请求的响应头,确认没有
X-Frame-Options: DENY或Content-Security-Policy: frame-ancestors 'none',否则 iframe 根本不会加载,和 sandbox 无关
最容易被忽略的是:sandbox 必须写死在 HTML 的 iframe 标签上,JS 动态设置(如 iframe.sandbox = 'allow-scripts')完全无效;另外,一旦子页用了 srcdoc 注入 HTML,它连 JS 都可能不执行,此时只有 sandbox 能兜底。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











