原型污染检测核心是确认污染是否穿透继承链并被执行:一查高危操作模式(递归赋值、深合并工具、动态路径访问);二运行时比对原型属性基线、验证实例继承行为;三冻结Object.prototype等关键原型;四监控第三方库初始化污染。

原型污染在前端安全中不是“有没有改”的问题,而是“改了之后是否被继承并执行”。检测与拦截要围绕污染是否真正穿透到运行时行为,而非仅检查代码里写了__proto__或constructor。
一、从源头识别高危操作模式
原型污染往往始于看似无害的数据合并逻辑。重点关注以下几类代码模式:
-
递归赋值语句:如
target[key] = source[key],且key来自用户输入(URL参数、表单、JSON解析结果) -
深拷贝/合并工具调用:lodash.merge、jQuery.extend、shvl.set、JSON.parse后直接遍历赋值等,尤其当传入对象含
__proto__、constructor.prototype等键名 -
动态属性访问:用点号或方括号访问深层路径(如
obj.a.b.c或obj[path]),而path未做白名单过滤 -
模板引擎配置注入:如EJS、Handlebars中将用户数据作为
locals传入,且模板内存在obj[key]式渲染
二、运行时主动检测污染痕迹
在页面加载早期(如<script></script>首屏脚本中)注入轻量检测逻辑,不依赖构建时扫描:
- 对
Object.prototype、Array.prototype、Boolean.prototype等原生原型,执行Object.getOwnPropertyNames(Obj.prototype),比对已知基线(如Chrome隐身页中执行结果),记录新增属性名 - 监听
Object.prototype上常见方法是否被重写:toString、valueOf、hasOwnProperty、isPrototypeOf——可临时替换为包装函数,首次调用时打印堆栈并告警 - 创建一个干净对象
const test = {},尝试访问可疑属性(如test.isAdmin、test.polluted),若返回非undefined且test.hasOwnProperty('isAdmin') === false,即确认已被污染
三、防御性锁定关键原型
冻结不是万能,但对核心原型加锁是成本最低的兜底措施:
- 在应用初始化最前头执行:
Object.freeze(Object.prototype)、Object.freeze(Array.prototype)、Object.freeze(Boolean.prototype)等。注意:IE不支持,但现代前端已基本不兼容IE - 对自定义基类(如
BaseModel、Store)的prototype同样冻结:Object.freeze(BaseModel.prototype),防止中间层被挂载钩子 - 若需兼容旧环境或部分库依赖可写原型,可用
Object.defineProperty逐个锁定关键属性:writable: false, configurable: false
四、监控第三方脚本行为
多数污染来自第三方库初始化阶段,而非业务代码:
- 审查引入的库文档,确认是否声明“会修改原生原型”(如旧版
moment、lodash某些构建版本) - 使用
PerformanceObserver或重写Function.prototype.toString(谨慎)捕获脚本执行时的原型修改动作 - 在
webpack或vite构建中启用module.rules对node_modules中疑似危险字符串(__proto__、constructor\.prototype)做静态告警
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











