防范原型污染漏洞关键在于阻断向Object.prototype写入属性的路径,需三方面协同:运行时冻结原生原型(如Object.prototype)、数据处理改用Object.create(null)、过滤敏感键名并升级安全依赖。

防范原型污染漏洞,关键在于阻断向 Object.prototype 写入属性的路径。这不是单点修补能解决的问题,需要从运行时防护、数据处理方式和依赖管理三方面协同落地。
冻结原生原型对象
在应用启动最早期(如 HTML 中首个 <script></script> 标签顶部),调用 Object.freeze() 锁定核心原型:
- 必须冻结:
Object.prototype、Array.prototype、Function.prototype、String.prototype、Boolean.prototype、Date.prototype - 严格模式下尝试修改会立即抛出
TypeError;非严格模式下赋值静默失败,同样生效 - 注意兼容性:极老环境(如 IE8)可能不支持,但现代项目基本无碍
避免用普通对象接收不可信输入
用户可控的数据(如 JSON 解析结果、URL 参数、表单提交)不应直接合并进 {} 类型对象:
使用约定式提交(Conventional Commits)生成标准化的 Git 提交信息。适用于以下场景: (1) 暂存更改时需要提交信息; (2) 审查 diff 时希望获得结构化摘要; (3) 编写 PR 描述或变更日志(changelog)条目; (4) 用户明确要求“为本次更改编写提交信息”。 该功能会分析已暂存/未暂存的 diff,并生成按类型(type)划分范围的提交信息。
- 改用
Object.create(null)创建无原型对象,它没有__proto__,属性查找失败即返回undefined,不会向上遍历 - 适用于路由参数、请求体解析、插件配置等场景
- 注意:这类对象不继承
toString、hasOwnProperty等方法,必要时用Object.prototype.hasOwnProperty.call(obj, key)替代
过滤敏感键名,坚持白名单机制
任何形如 target[key] = source[key] 的赋值,只要 key 来自外部输入,就必须拦截危险键:
- 明确禁止:
"__proto__"、"constructor"、"prototype"及其大小写变体(如"__PROTO__") - 深合并逻辑需在每一层递归前检查当前
key,不能只校验顶层 - 优先采用白名单:只允许已知安全字段(如
["name", "email"])进入目标对象
升级依赖并选用安全 API
很多污染漏洞源于工具链缺陷,主动规避风险比事后修复更有效:
- 升级
lodash至4.17.21+,其merge已默认跳过__proto__ - 避免使用已知有风险的深拷贝库(如旧版
deepmerge) - 现代环境优先用原生
structuredClone(),它不遍历原型链、不执行 getter,更安全 - Node.js 后端可启用
--disable-proto=throw运行参数强制拦截

















