直接冻结原生类型prototype是最有效防护方式,需在脚本早期调用Object.freeze()锁定Object、Array、String等关键原型,阻止新增/删除/重写属性,但不冻结实例或原型链其他对象。

直接冻结原生类型的 prototype 对象,是保护原型链最有效、最常用的方式。它能阻止攻击者或误操作向 String.prototype、Object.prototype 等添加或覆盖方法,从而切断原型链污染的入口。
冻结关键原型对象
应在脚本执行早期(比如全局作用域顶部、任何第三方库加载前)调用 Object.freeze(),锁定核心原型:
-
Object.freeze(Object.prototype)—— 最重要,防止污染全局对象行为 Object.freeze(Array.prototype)Object.freeze(String.prototype)Object.freeze(Number.prototype)Object.freeze(Boolean.prototype)
注意:冻结必须在任何可能修改原型的代码之前完成;若已遭篡改,freeze 无法恢复原始方法,仅能阻止进一步改动。
理解 freeze 的作用边界
Object.freeze() 作用于原型对象本身,不是实例。它确保:
立即学习“Java免费学习笔记(深入)”;
- 不能新增属性(如
Object.prototype.polluted = true失败) - 不能删除已有属性(如
delete Object.prototype.toString失败) - 不能重写现有方法(如
Object.prototype.toString = () => 'hacked'失败) - 不能修改属性描述符(
writable、configurable全部设为false)
但它不冻结原型链上的其他对象,也不影响实例自身的可变性——只守住“源头”。
配合其他防护手段更稳妥
单靠冻结原型不能解决全部问题,建议组合使用:
- 对用户输入参与的对象合并(如
_.merge、deepAssign)做键名校验,拒绝__proto__、constructor、prototype等敏感键 - 使用
Object.create(null)创建无原型的对象(如配置缓存、映射表),彻底脱离原型链 - 在 Node.js 环境中,可通过
vm.Context或SES(Secure EcmaScript)沙箱进一步隔离
不推荐深冻结原型对象
原型对象(如 Array.prototype)内部包含大量函数和不可枚举属性,递归深冻结不仅没必要,还可能引发兼容性问题或性能开销。冻结顶层原型即可阻断污染路径——因为污染的本质是往 Object.prototype 写属性,而不是改它的某个嵌套字段。


















