object.isextensible无法防御eval污染,因其仅检测对象是否可扩展,而eval在非严格模式下通过globalthis.x=1方式赋值,不触发扩展性检查;真正防护需禁用eval、使用function构造函数、启用严格模式或沙箱隔离。

Object.isExtensible 本身无法防御 eval 引起的全局对象污染,它只能判断对象是否允许新增属性,而 eval 在非严格模式下向全局作用域注入变量时,本质是给全局对象(如 window 或 globalThis)赋值——这属于属性写入或定义操作,与对象是否可扩展无直接关系。
为什么 isExtensible 对 eval 污染“无效”
原因在于:
-
eval('var x = 1')在非严格模式下等价于globalThis.x = 1(或window.x = 1),只要全局对象该属性尚未存在,就会执行属性创建;若已存在,则是赋值,不涉及扩展性检查。 - 全局对象默认是可扩展的(
Object.isExtensible(globalThis) === true),但即使设为不可扩展(Object.preventExtensions(globalThis)),也无法阻止对已有属性的修改或重新赋值,更不能拦截var/let/const声明在eval中的绑定行为(后者由执行上下文决定,非单纯属性操作)。 -
Object.isExtensible是只读检测,不具备防护能力,也不能触发拦截或抛错。
真正有效的防御方向:隔离 + 限制 + 替代
应对 eval 全局污染,应放弃依赖元属性检测,转而采用运行时控制策略:
-
禁用或沙箱化 eval:生产环境避免使用
eval;必须动态执行时,改用Function构造函数(作用域封闭,不污染全局),例如:const fn = new Function('a', 'return a + 1'); -
冻结全局对象(谨慎使用):可在初始化后调用
Object.freeze(globalThis),阻止新增、删除、配置属性,且已有属性设为只读。注意:这会影响依赖动态挂载的库(如某些 polyfill),需充分测试。 -
启用严格模式:在
eval字符串开头加'use strict';,使其中的var声明不会泄漏到全局,而是仅存在于eval自身作用域内。 - 使用 Web Worker 或 iframe 沙箱:将不受信代码放入独立上下文执行,完全隔离全局对象。
可配合 isExtensible 的辅助监控场景
虽然不能防御,但可在开发/测试阶段用 Object.isExtensible 做一致性断言:
- 启动时检查
Object.isExtensible(globalThis)是否为true,若预期已冻结却仍可扩展,说明防护逻辑未生效。 - 在关键流程前后比对全局对象是否仍可扩展,作为“被意外修改”的粗略信号(非可靠指标,仅辅助排查)。
不复杂但容易忽略:防护核心不在检测,而在从源头切断污染路径。eval 是高危操作,优先消除其使用,其次才考虑运行时加固。










