严格模式下直接修改__proto__会抛出TypeError,但需配合冻结Object.prototype、使用Object.create(null)及过滤敏感键才能实现真正安全。

在严格模式下,直接修改 __proto__ 属性本身就会抛出 TypeError,这是语言层的硬性限制,无需额外代码即可生效。
严格模式自动禁止 __proto__ 赋值
只要脚本或函数处于严格模式(通过 "use strict" 声明),对 __proto__ 的写操作会立即失败:
-
obj.__proto__ = {}→ 抛出TypeError: Cannot set property __proto__ of #<object> which has only a getter</object> -
Object.defineProperty(obj, '__proto__', { value: {} })→ 同样报错,因该属性默认不可配置、不可写 - 即使对象是新创建的(如
const obj = {}),只要上下文是严格模式,赋值即中断
但仅靠严格模式不够,还需切断其他污染路径
攻击者可能绕过 __proto__ 直接写法,改用间接方式污染原型链。因此必须配合以下措施:
- 在所有代码执行前冻结
Object.prototype:Object.freeze(Object.prototype) - 避免使用
{}作为数据容器,改用Object.create(null)创建无原型对象 - 解析用户输入(如 JSON)后,手动过滤掉
__proto__、constructor、prototype等键名 - 禁用存在风险的工具函数,例如旧版
lodash.merge;优先使用structuredClone或白名单校验的深拷贝逻辑
真正安全的关键是“防御纵深”
严格模式只是第一道门,它拦得住显式赋值,但拦不住:
立即学习“Java免费学习笔记(深入)”;
- 通过
constructor.prototype修改(如{}.constructor.prototype.admin = true) - 利用有缺陷的合并逻辑把恶意键注入普通对象,再被后续代码沿原型链读取
- 第三方库在非严格模式下运行并执行危险操作
所以必须冻结原生原型 + 使用无原型对象 + 过滤敏感键,三者缺一不可。


















