排查原型污染关键在于确认污染方法是否被子类无意继承并执行非预期逻辑,需从检测(比对prototype属性)、验证(实例调用+hasOwnProperty检查)、监控(锁定属性/拦截setter)、回溯(扫描setPrototypeOf/不安全合并)四层面系统切入。

排查 JavaScript 继承机制中的原型污染与继承漏洞,关键不是“有没有改原型”,而是“改了之后是否被子类无意继承并执行非预期逻辑”。污染常藏在看似无害的扩展、第三方库初始化或手动设置原型链的过程中,需从检测、验证、监控、回溯四个层面系统切入。
检查基类 prototype 是否存在非预期方法
污染往往始于对 Object、Array 或自定义基类(如 BaseModel)prototype 的非法写入。直接运行以下命令对比基线:
- Object.getOwnPropertyNames(Object.prototype) —— 在干净环境(如新标签页)中记录初始结果,上线后再次比对,识别新增项
- 重点筛查:toString、valueOf、hasOwnProperty、constructor 等原生方法名是否被覆盖;也留意非常规命名如 exec、run、isAdmin、_payload 等可疑钩子
- 对项目中所有自定义基类(尤其是被多处继承的类)同样执行 Object.getOwnPropertyNames(BaseClass.prototype),避免只盯 Object 而漏掉中间层污染
验证子类实例是否实际继承污染方法
仅看原型上有无属性不够,必须确认该方法是否穿透继承链、影响运行时行为:
- 新建干净实例:const inst = new ChildClass(),然后调用疑似方法:inst.suspiciousMethod()
- 若调用成功且返回异常结果(如固定字符串、静默发起请求、抛出非标准错误),而该方法未在 ChildClass 或其直接父类中定义,即为污染信号
- 进一步验证:inst.hasOwnProperty('suspiciousMethod') === false,但 typeof inst.suspiciousMethod === 'function',这是典型污染特征
锁定关键 prototype 属性并监控动态修改
在开发或测试环境注入轻量防护,主动拦截非法写入:
- 对高危类(如 Object、Array、BaseModel)的 prototype 执行属性锁定:Object.defineProperty(Target.prototype, 'methodName', { writable: false, configurable: false })
- 临时劫持 setter:例如重写 Parent.prototype.__defineSetter__('dangerousMethod', () => { throw new Error('Blocked! Stack: ' + new Error().stack) })
- 特别注意第三方库加载阶段(如 moment、lodash、某些 UI 库),它们常在初始化时向原型挂载工具方法,需查阅其文档或源码确认是否声明了此类行为
回溯高危继承代码模式
污染高频出现在“手动增强继承能力”的场景中,重点扫描以下模式:
- Object.setPrototypeOf(Child.prototype, Parent.prototype) —— 显式篡改原型链,且未冻结或校验来源
- 使用 for...in 遍历对象并递归合并属性(尤其处理用户输入或外部 JSON 时),易触发 __proto__ 或 constructor 键污染
- 自定义 merge、deepClone、assign 工具函数,未过滤原型属性键名(如 __proto__、constructor、prototype)











