避开原型污染的关键是防止向object.prototype写入及避免被污染属性干扰,需用object.prototype.hasownproperty.call()校验自有属性、用object.keys()遍历、创建object.create(null)无原型对象、对动态属性名白名单校验或使用map。

要避开原型污染,关键不是“怎么查找属性”,而是查找时避免意外访问和修改 Object.prototype。JavaScript 中属性查找本身(如 obj.prop)天然走原型链,无法绕过;真正需要防范的是:往原型上写(污染),以及不加防护地读/遍历时被污染的属性干扰。
用 hasOwnProperty() 判断自有属性
这是最基础也最关键的防护手段。它只检查对象自身是否拥有该属性,不查原型链:
-
obj.hasOwnProperty('x')返回true仅当x是obj自己的属性 - 对从
Object.create(null)创建的对象也安全(它没有原型,hasOwnProperty不会报错,但需注意调用方式:Object.prototype.hasOwnProperty.call(obj, 'x')) - 避免直接写
obj.hasOwnProperty('x')—— 如果obj被污染(比如obj.hasOwnProperty = null),会出错;推荐统一用Object.prototype.hasOwnProperty.call(obj, key)
遍历时过滤掉原型属性
用 for...in 遍历对象时,默认包含原型链上的可枚举属性。污染后可能多出意外键(如 __proto__、constructor、或恶意注入的 admin):
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 始终配合
hasOwnProperty使用:for (let k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) { /* 处理 k */ } } - 优先使用
Object.keys(obj)—— 它只返回对象自身的可枚举属性数组,天然免疫原型污染 - 需要不可枚举属性时,用
Object.getOwnPropertyNames(obj)或Object.getOwnPropertyDescriptors(obj)
创建对象时切断原型链(防御性初始化)
如果对象内容完全来自外部(如 JSON 解析、用户输入),主动让它不继承 Object.prototype,从源头杜绝污染影响:
-
const safeObj = Object.create(null)—— 创建无原型的对象,safeObj.toString、safeObj.hasOwnProperty等都不存在,彻底干净 - 解析 JSON 后立即转为无原型对象:
Object.assign(Object.create(null), JSON.parse(input)) - 注意:这种对象不能直接调用
toString()等方法,需自行实现或转回普通对象(仅在必要时)
谨慎处理动态属性名和外部数据
原型污染常发生在把用户可控的 key 直接赋值给对象时(如 obj[userInput] = value):
- 禁止将未校验的字符串作为属性名直接写入普通对象,尤其避免
__proto__、constructor、prototype - 写入前做白名单校验:
if (['name', 'age', 'email'].includes(key)) { obj[key] = value } - 或统一用
Map存储动态键值对:const map = new Map(); map.set(userKey, value);——Map不受原型链影响,且 key 可为任意类型
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










