原型链污染是JavaScript中因不当处理对象属性导致的高危安全问题,攻击者通过控制输入向Object.prototype写入恶意属性,影响所有对象行为;其发生源于对象属性访问时沿原型链查找,若未防护地递归赋值用户可控数据(如JSON、URL参数),可能意外修改__proto__或constructor.prototype;常见触发点包括使用存在缺陷的深拷贝工具、手动递归赋值未过滤敏感键、直接解析含{"__proto__":{}}的JSON;防御核心是不信任任何输入,升级修复版本依赖、过滤敏感键名、采用白名单机制、使用安全替代方案(如structuredClone)、冻结原型及运行时监控。

原型链污染是 JavaScript 中一种因不当处理对象属性而导致的高危安全问题,本质是攻击者通过控制输入,向 Object.prototype 写入恶意属性,从而影响所有对象的行为。
污染是如何发生的
JavaScript 的对象在访问属性时会沿原型链向上查找。若代码未加防护地将用户可控数据(如 JSON 解析结果、URL 参数、表单字段)递归赋值到普通对象,就可能意外修改 __proto__ 或 constructor.prototype,进而污染全局原型。
常见触发点包括:
- 使用浅/深拷贝工具(如
lodash.merge、_.set)处理不可信输入时未禁用原型键 - 手动实现递归赋值逻辑,且未过滤
__proto__、constructor、prototype等敏感键名 - 将用户提交的 JSON 字符串直接
JSON.parse()后合并进配置对象,而该 JSON 包含{"__proto__": {"admin": true}}
关键防御手段
核心原则是:永远不把不可信输入当作对象路径或属性名来使用,尤其避免递归写入操作。
-
升级并锁定依赖版本:确认使用的工具库(如 lodash lodash.merge 默认允许污染,新版需显式启用
customizer或改用lodash.assignInWith控制行为 -
输入清洗与白名单校验:对所有外部输入,在解析或赋值前过滤掉
__proto__、constructor、prototype及其大小写变体(如__PROTO__);优先采用字段白名单机制,只允许明确声明的属性被设置 -
使用安全的替代方案:避免通用深拷贝函数;可用
Object.assign({}, input)做浅拷贝;需要深拷贝时,用structuredClone(现代环境)或自定义函数跳过原型相关键;Node.js 中可启用--disable-proto=throw运行参数强制拦截
运行时防护建议
在关键服务中增加额外保护层,提高攻击门槛。
- 启动时冻结原型:执行
Object.freeze(Object.prototype)和Object.freeze(Function.prototype)(注意兼容性,部分老环境可能报错) - 监控异常属性写入:通过重写
Object.prototype.__defineSetter__或利用Proxy包裹全局对象(仅限开发/测试环境,生产慎用)捕获可疑操作 - 启用严格模式与 CSP:虽不能阻止污染本身,但可限制后续利用(如禁止 eval、限制内联脚本),降低 RCE 或 XSS 风险
原型链污染不是语法缺陷,而是设计误用与信任边界模糊的结果。只要坚持“不信任任何输入”和“最小权限赋值”,就能有效规避绝大多数场景下的风险。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











