最直接有效的方式是在所有脚本执行前冻结Object.prototype,并配合无原型对象创建和输入过滤形成三重防护;需第一时间在首个<script>顶部执行Object.freeze(Object.prototype),同时冻结Array、Function等关键原型,用Object.create(null)替代{}创建对象,过滤__proto__、constructor等敏感键名,并升级lodash、启用Node.js--disable-proto=throw等环境加固措施。

最直接有效的方式是在所有脚本执行前冻结 Object.prototype,同时配合无原型对象创建和输入过滤,形成三重防护。
第一时间冻结原生原型
必须在页面中第一个 <script> 的顶部立即执行,确保早于任何第三方库、框架或用户代码:
-
Object.freeze(Object.prototype)是核心动作,它让所有属性变为不可写、不可配置、不可枚举 - 顺带冻结其他关键原型:
Array.prototype、Function.prototype、String.prototype、Boolean.prototype、Date.prototype - 严格模式下尝试修改会抛出
TypeError;非严格模式下赋值静默失败,同样阻断污染
用 Object.create(null) 替代普通空对象
避免把污染风险传导到业务数据层:
- 路由参数、表单配置、请求体解析结果等可能受控的场景,统一用
Object.create(null)创建容器 - 这类对象没有
__proto__,不会继承Object.prototype上的任何属性或方法 - 注意兼容性:调用
hasOwnProperty改为Object.prototype.hasOwnProperty.call(obj, key),避免直接使用obj.toString()
过滤敏感键名,堵住污染入口
只要存在 target[key] = source[key] 类逻辑,且 key 来自外部(如 JSON 解析、URL 参数),就必须拦截:
立即学习“Java免费学习笔记(深入)”;
- 明确禁止以下键:
"__proto__"、"constructor"、"prototype",包括大小写变体(如"__PROTO__") - 对深合并或递归赋值函数,每一层都要检查当前 key,不能只校验顶层
- 解析用户输入后,不直接
Object.assign({}, input),优先走白名单字段校验
环境与依赖加固
单靠运行时防护不够,需结合工程实践:
- 升级 lodash 至 4.17.21+,避免旧版
_.merge的污染漏洞 - Node.js 环境可启用
--disable-proto=throw启动参数,让__proto__访问直接报错 - 前端构建时引入 ESLint 规则,禁止裸写
Object.prototype.xxx =或Array.prototype.xxx =


















