关键在于验证属性名是否符合预期,需主动核对自有属性清单、检查原型链污染、拦截高危写入源头。

关键不是“有没有”,而是“是不是预期的那个”。属性名是否与预期一致,直接影响数据结构可靠性、安全边界和逻辑执行路径。重点在于主动验证而非被动假设。
核对自有属性清单
先确认对象自身是否干净、字段是否符合契约:
- 用 Object.keys(obj) 快速列出所有可枚举自有属性,比对是否多出或缺失关键字段(如意外出现
__proto__、admin、run) - 补充调用 Object.getOwnPropertyNames(obj),捕获不可枚举属性(比如某些库注入的隐藏控制字段)
- 若存在明确字段白名单(如
['id', 'name', 'email']),直接检查Object.keys(obj)是否完全落在该集合内,多余项即为异常
排查原型链污染
很多“不一致”其实来自原型被篡改,影响所有实例:
- 执行 Object.getOwnPropertyNames(Object.prototype),查看是否有业务无关的键(如
isAuth、exec、大小写变体Constructor) - 逐级打印
obj.__proto__、obj.__proto__.__proto__,定位哪一层混入了非标准属性 - 特别注意
constructor、prototype、__proto__是否被赋值——它们一旦出现在实例上,往往意味着污染已发生
拦截高危写入源头
属性名失序常源于外部输入未过滤就合并进对象:
- 搜索代码中
Object.assign({}, userInput)、lodash.merge({}, data)类调用,尤其当userInput来自 URL、表单或 API 响应时 - 旧版 Lodash(merge 默认允许
__proto__写入,升级或改用lodash.assignIn可规避 - 在关键赋值前加断点,观察
key变量值——若为"constructor"或带双下划线的字符串,基本就是污染入口
运行时轻量校验
上线后也可嵌入低成本防护:
- 启动时执行 Object.freeze(Object.prototype),后续任何修改都会报错(注意 IE 不支持)
- 在关键对象生成后调用简易校验函数,例如:
if (typeof obj !== 'object' || obj === null) return;
const keys = Object.keys(obj);
const illegal = keys.filter(k => !allowed.includes(k));
if (illegal.length) console.warn('Unexpected keys:', illegal);
}

















