MCP 多语言 SDK 暴露请求体耗尽内存风险
文章追踪一种 MCP 拒绝服务缺陷:HTTP 请求体读取没有大小限制,单个未认证请求即可耗尽服务端内存。据作者梳理,同类问题随后在至少九个其他 MCP 项目中发现并修复,涉及多个官方语言 SDK。
AI 深度解读
一个 MCP 服务即使配了鉴权,也可能被一条未登录的请求拖垮:如果程序先把 HTTP 请求体完整读进内存,再检查身份和消息大小,攻击者就能在检查发生前耗尽内存。
作者追踪的是这类缺陷如何从一个 TypeScript 框架扩散到多个官方 SDK,以及补丁发布后,为什么依赖扫描仍可能报不出来。对部署远程 MCP 服务的团队,最有用的提醒是:检查输入限制究竟在哪里执行,同时直接核对依赖版本。
配了消息大小限制,为什么服务器还会崩
原文的起点是作者报告的 CVE-2026-39313。mcp-framework 在 0.2.21 及更早版本中,HTTP transport 的 readRequestBody() 持续把数据块拼接成字符串,却没有限制累计大小。
框架其实提供了 maxMessageSize 配置,但这个函数根本没有读取它。向 /mcp 发送一个大 POST,就可能在消息检查之前耗尽进程内存。该问题于 2026 年 4 月 16 日公开,0.2.22 修复,CVSS 4.0 评分为 8.7,归类为 CWE-770,即分配资源时没有设置边界。
限制写在配置里,不等于限制已经保护了资源分配。
这里要区分两个时机:先限制输入,再读取;或者先读完,再判断是否超限。后者即使最终拒绝请求,内存也已经分配出去了。鉴权同理:如果它排在完整读取请求体之后,就挡不住这条消耗路径。
作者描述的攻击既可以是超大请求,也可以是持续发送的数据流。服务不断缓存,最终可能被内存不足终止机制杀掉。攻击目标是可用性,原文没有声称涉及数据窃取。
为什么同一个问题会出现在多个 SDK
作者列出的时间线,说明这不是单个项目漏写了一次判断。
4 月首份公告之后,Google MCP Toolbox for Databases 被报告存在无限制的 io.ReadAll,6 月修复;官方 Go SDK 在 7 月加入请求体上限,两者都没有对应 CVE。
7 月 30 日公开的 Ruby SDK 漏洞 CVE-2026-67432 提供了一组直观数据:512 MB POST 让 worker 内存从 44 MB 增至 1.66 GB,修复后默认限制为 4 MiB。这是原文引用的个案数据,不能直接当作其他语言实现的内存放大比例。
随后还有 PHP SDK 的 CVE-2026-53965、Rust rmcp 的 CVE-2026-63128,以及 mcp-go 的 CVE-2026-108859。PHP 的问题是客户端 SSE 缓冲区无上限,Java SDK 同日在 8 月 19 日修复了类似客户端问题。这与服务端读取请求体属于相近的资源失控模式,但攻击入口不同。
10 月 14 日,官方 Python 和 Java SDK 分别公开 CVE-2026-109527、CVE-2026-108395,评分均为 CVSS 7.5。10 月 20 日及 27 日,官方 TypeScript SDK 又出现 CVE-2026-111768 和后续公告。
Python 的影响面包括 Streamable HTTP session manager、SSE 消息端点和 OAuth 授权服务器路由。原文列出的受影响版本是低于 1.29.1,以及截至 2.0.1 的 2.0 预发布版本;明确给出的修复版本是 1.29.1。因此,不能仅凭主版本号更大就判断已经安全。
作者认为,重复出现的原因之一是规范缺位:截至 2026 年 11 月初,MCP 安全最佳实践仍未明确指导实现者限制请求体大小,各 SDK 只能分别补上,默认值通常是 4 MiB。
为什么补丁发布了,扫描器仍可能保持安静
原文最有实际价值的部分,是把「漏洞已公开」和「依赖扫描能匹配」拆开了。
据作者截至 2026 年 11 月 3 日的检查,mcp-framework 的公告已进入全局 GitHub Advisory Database 和 OSV,npm audit 能识别受影响版本。但 Python 与 Java 的上述两个 CVE,当时只有仓库级公告,没有进入全局 GitHub 公告库。
作者列出的后续断点包括:Dependabot 缺少对应公告;OSV 缺少记录,依赖它的 osv-scanner 无法匹配;PyPA 公告库没有相应记录,pip-audit 也无法据此告警;NVD 虽已收录,却处于 Awaiting Analysis,没有可用于匹配的版本范围。
扫描结果为空,只能说明工具在已有数据里没有匹配到问题。
这些状态有明确日期,可能在数据库更新后改变。本文仅根据所给原文解读,没有独立核验当前收录情况。
发行版安全团队则有另一条信息链路。作者列出 Red Hat 对 Python 漏洞评估的 44 个产品:35 个受影响、6 个不受影响、3 个标记为 will-not-fix,并发布三份勘误。Debian 将 python-mcp 的问题定为 grave,原文写作时 unstable 中仍未修复。
影响规模也需要读准:原文给出的月下载量是 Python 约 2.35 亿、TypeScript 约 2.57 亿,合计接近 5 亿,并非 Python 与 Java 的合计。下载量能说明依赖传播范围,但不等于公网暴露实例数。
我的判断
作者最有说服力的判断,是应该在读取输入时建立资源边界。对 Node 开发者,这对应一个很具体的检查:看到 string += chunk 一类累加逻辑,就要继续找累计大小在哪检查,不能只确认后面的 JSON 校验或鉴权是否存在。
但「一种全新漏洞类别」需要打个问号。作者自己也将它归为已有的 CWE-770。更准确的理解是,一种老问题在 MCP HTTP 实现中集中暴露。规范没有明确要求可能助长遗漏,但原文没有提供对照研究,无法证明规范缺位就是各项目出现漏洞的共同原因。
暴露条件也不能省略:运行受影响实现、启用 HTTP transport,并且不完全可信的客户端能够访问。仅使用 stdio 的服务,不处于同一条攻击路径;已经通过反向代理限制请求体的部署,风险也不同。
代理限制适合快速缓解,SDK 内部限制则能约束应用自身的读取行为。两者可以同时使用。至于持续流、并发请求和客户端 SSE 缓冲,不能只凭一个请求体上限就宣布全部解决,原文没有给出覆盖这些条件的完整验证。
能拿来做什么
-
先盘点生产 MCP 服务使用的是 stdio、Streamable HTTP 还是 SSE,并确认共享内网、浏览器可达入口及公网入口中,哪些允许不可信客户端访问。
-
直接核对依赖版本。原文明确列出的修复版本包括 mcp-framework 0.2.22、Python
mcp1.29.1、官方 Go SDK v1.7.0、Rubymcpgem 0.23.0。Java 只写了修复后的mcp-core,其他若干项目只要求升级到最新版,没有给出精确修复版本,不能据此编造版本门槛。 -
暂时无法升级时,在反向代理配置请求体限制,例如 nginx 的
client_max_body_size,并检查能否绕过代理直连服务。Python 可显式设置max_request_body_size,其DEFAULT_MAX_REQUEST_BODY_SIZE为 4 MiB;Go 的DefaultMaxRequestBodyBytes同为 4 MiB,实际取值应结合合法载荷确定。 -
检查自定义 transport 的读取逻辑,重点搜索 Go 的
io.ReadAll(r.Body)、Ruby 的request.body.read和 Node 的string += chunk。确认大小检查发生在持续累积数据的过程中,再用受控超限请求验证拒绝行为和内存变化。