原型污染是原型链被恶意修改的安全问题,需通过创建无原型对象、冻结关键原型、校验输入键名等方式防止污染。

原型污染本身是原型链被恶意修改导致的安全问题,不是用原型链“解决”它,而是要防止原型链被污染。关键在于拦截或规避对 Object.prototype(或其上游如 Array.prototype)的任意属性写入。
避免直接操作原型对象
很多漏洞源于将用户输入(如 JSON 解析结果、URL 参数、配置合并逻辑)无校验地赋值给对象属性,而该对象又未设置原型隔离。
- 不要用
obj[key] = value处理不可信的key,尤其当key === "__proto__"或"constructor.prototype"时会触发污染 - 改用
Object.defineProperty(obj, key, { value, writable: true, enumerable: true, configurable: true }),它默认不会触发原型赋值(但需注意:若obj是空对象且原型为Object.prototype,仍可能间接影响——所以更推荐下一条)
使用 Object.create(null) 创建无原型对象
这是最常用、最有效的防御方式:让数据容器不继承 Object.prototype,彻底切断污染路径。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 解析用户 JSON 后,立即用
JSON.parse(str, (k, v) => k === '' ? Object.create(null) : v)或递归替换普通对象为Object.create(null) - 配置合并工具(如 Lodash 的
merge)默认不安全;可先深克隆为 null 原型对象,或改用structuredClone(现代环境)+ 后续冻结 - 示例:
const safeObj = Object.create(null); safeObj.__proto__ = 'harmless'; // 不会影响全局 Object.prototype
冻结原型 + 属性访问控制
在应用启动时锁定关键原型,配合严格模式运行。
- 执行
Object.freeze(Object.prototype)和Object.freeze(Array.prototype)(注意:部分旧环境不支持冻结原型,且不能回退) - 搭配
"use strict",让向不可写原型属性赋值抛出错误(而非静默失败) - 使用
Object.hasOwn(obj, prop)替代obj.hasOwnProperty(prop),避免调用被污染的hasOwnProperty方法
输入校验与深度遍历防护
对所有外部输入做白名单键名过滤,尤其拦截高危键:
- 禁止键名包含
"__proto__"、"constructor"、"prototype"(大小写敏感或不敏感,视需求而定) - 在 deep-merge / deep-set 类函数中,递归检查每个 key,遇到危险键直接跳过或报错
- 使用已审计的安全库,如
fast-deep-equal配合safe-merge,或启用 Node.js 的--disable-proto=throw启动参数(v12.19+)
不复杂但容易忽略:原型污染不是代码写得“不够面向对象”,而是信任了不该信任的数据源。守住入口、隔离原型、冻结关键对象,就能有效阻断污染链。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










