instanceof在原型污染下完全不可信,因其仅遍历原型链而不校验合法性,污染object.prototype或构造函数prototype会导致判断结果失真,故不可用于权限或类型校验。

instanceof 在原型污染攻击下完全不可信,它不是安全检测机制,而是原型链遍历的“旁观者”——污染一旦发生,它的判断结果就会被扭曲。
instanceof 的本质是原型链查找
它只做一件事:从左侧对象的 __proto__ 开始,逐层向上比对是否等于右侧构造函数的 prototype。整个过程不校验原型是否被篡改、是否合法、是否被冻结。
这意味着:只要攻击者成功向 Object.prototype 注入属性(如 admin: true),或更隐蔽地替换某个构造函数的 prototype,instanceof 就会照常返回 true 或 false,但结果已失去业务语义。
原型污染如何直接干扰 instanceof 判断
以下三类污染可导致 instanceof 行为异常:
- 覆盖目标构造函数的
prototype:例如Array.prototype = { constructor: String },会导致[].constructor === String,进而使[] instanceof Array返回false - 污染
Object.prototype.constructor:若设Object.prototype.constructor = EvilClass,则所有普通对象(如{}、[])的constructor都指向EvilClass,影响依赖obj.constructor === X的逻辑 - 冻结或替换内置原型后仍允许污染传播:比如
Object.freeze(Object.prototype)能防新增属性,但若污染发生在冻结前,或通过__proto__动态赋值绕过(如obj.__proto__ = EvilProto),instanceof 依然会按被污染的链路返回结果
不能用 instanceof 做权限/类型校验
常见错误写法:
❌ 危险示例if (user instanceof AdminUser) { grantAdminAccess(); }
攻击者只需触发一次原型污染(如通过合并含 {"__proto__": {"constructor": AdminUser}} 的数据),就能让任意普通用户对象满足该条件。
真正安全的替代方式包括:
- 使用
Object.prototype.toString.call(obj)获取精确内置类型标识(如[object Object]) - 基于白名单的显式属性检查(如
obj && typeof obj === 'object' && 'isAdmin' in obj && obj.isAdmin === true) - 服务端始终以独立、不可篡改的状态(如 JWT payload、数据库字段)判定权限,绝不依赖前端传入对象的
instanceof结果
检测污染是否影响 instanceof 的简单方法
在关键逻辑执行前快速验证原型链完整性:
- 检查
Object.getPrototypeOf({}) === Object.prototype是否仍为真 - 确认
Array.prototype.constructor === Array和Object.prototype.constructor === Object - 对关键构造函数调用
Object.isFrozen(XXX.prototype)(仅限已冻结场景)
这些检查不能替代输入过滤和运行时加固,但可作为污染发生后的快速熔断信号。










