iframe 本身不污染全局变量,污染源于跨上下文操作:子页脚本直接赋值 parent.xxx、eval 远程代码、document.write 注入父上下文脚本,或第三方 SDK 擅自修改 window.parent。

iframe 本身不会污染全局变量,但它的加载行为会触发脚本执行污染
iframe 不是“变量容器”,它不直接往 window 上挂变量。真正造成全局污染的是 iframe 加载的页面里执行的 JavaScript —— 尤其是那些没用 type="module"、没包 IIFE、甚至直接写 var foo = 1 的脚本。
常见触发场景:
- 父页通过
iframe.src = "child.html"加载含裸var声明的子页,子页 JS 执行后,foo就挂在了子页自己的window上——但这对父页无影响;可一旦子页用了document.write或动态插入 script 标签,且脚本在父上下文执行(比如通过parent.eval()),就可能污染父页 - 用
iframe.contentWindow.document.write()注入 HTML 字符串,里面含内联<script>var x=1</script>:这段脚本在 iframe 的上下文中运行,x属于子页window,仍不污染父页;但若注入的是<script>parent.x=1</script>,那就直接写到父页全局了 - 第三方 iframe(如广告、统计 SDK)主动调用
parent.postMessage并附带恶意 payload,再由父页未校验 origin 的监听器执行eval(event.data.code),等于把远程代码扔进父页全局作用域
为什么 iframe.contentWindow 有时像“全局变量”一样被误用
这不是污染,是引用泄漏。当你把 iframe.contentWindow 赋值给一个长期存活的变量(比如 window.iframeWin = iframe.contentWindow),这个引用会阻止 iframe 内部文档被 GC,同时让子页 window 对象在父页中可访问——看起来像“暴露了全局变量”,实则是内存和作用域边界的混淆。
典型错误写法:
立即学习“前端免费学习笔记(深入)”;
const win = iframe.contentWindow; // 没清空,win 一直活着- 在弹出层组件中缓存
this.iframeWin = iframe.contentWindow,关闭弹窗时只删 DOM,不设this.iframeWin = null - 监听
message时没绑定到具体 iframe 实例,而是用全局window.addEventListener('message', handler),导致 handler 闭包持有了不该持有的contentWindow引用
如何确认污染源来自 iframe 加载的内容
别猜,用 DevTools 直接定位。打开 Sources → Page,展开 iframe 对应的域名或 about:blank 页面,看它的 Console 输出或 Snippets 中执行 Object.keys(window),对比父页结果。重点查:
- 新增的变量名是否与 iframe 页面 JS 文件名/功能相关(如
adSdkInit、analytics_v2) - 该变量是否在 iframe 卸载后仍存在于父页
window—— 如果还在,说明有显式赋值或 eval 注入 - 执行
iframe.contentWindow === window返回false,但iframe.contentWindow.constructor === window.constructor为true,说明仍是独立上下文,污染必来自跨上下文操作(如parent.xxx、eval、Function构造)
真正要防的不是 iframe,而是跨上下文执行逻辑
所有“iframe 引发的全局污染”,本质都是父页或子页主动越界操作的结果。安全边界只有一条:不同 window 对象之间,不允许任何直接属性读写或函数调用,只能走 postMessage + 严格 origin 校验。
必须切断的链路:
- 禁用所有
parent.xxx/top.xxx/opener.xxx赋值,改用postMessage发指令 - 子页内避免使用
eval、Function、setTimeout("...")解析来自父页的字符串 - 父页接收
message后,绝不eval(event.data.script)或new Function(event.data.fn)(),只处理结构化数据 - 第三方 iframe 必须用沙箱属性:
<iframe sandbox="allow-scripts" src="...">,禁用allow-same-origin防止它伪造同源身份
最易被忽略的一点:即使你没写任何跨上下文代码,某些老旧 SDK(如部分统计埋点)会在 iframe 内自动执行 window.parent.xxx = ...,这种行为无法靠 CSP 拦截,只能靠沙箱或提前重写 window.parent 访问器来防御。



















