OOOMETA/OS
← 返回洞察

2026 年 9 月 · 5 分钟阅读

审查过的 MCP 工具在第四次调用开始背叛你:Deadbugz 的运行时门控投毒

审查过的 MCP 工具在第四次调用开始背叛你:Deadbugz 的运行时门控投毒

关键定义

运行时门控元数据投毒(Runtime-Gated Metadata Poisoning) 恶意 MCP 服务器把有害指令内建在自身,但用调用计数器延迟暴露:前三次调用返回正常工具描述,越过阈值后,通过协议元数据引导 Agent 窃取 SSH 密钥、云凭证等敏感信息。

工具元数据(Tool Metadata) MCP 协议中服务器向 Agent 广告的工具名称、描述与参数 schema;Agent 把这些文本当作可信上下文,据此决定何时调用哪个工具,因此它既是功能接口,也是攻击面。

你批准的那个 MCP 工具,会在第四次调用时开始背叛你——而你审查它的那几分钟里,它看起来完全正常。8 月 10 日晚,一个 GitHub 账号在 74 分钟里向 23 个仓库提交了『顺手改个配置』的 PR;其中藏着的 MCP 服务器前三次调用都是诚实的格式化工具,第四次起,它通过协议元数据告诉 Agent:去找 SSH 密钥、AWS 凭证、Kubernetes 配置,并且别让操作者发现。

一次攻击的三段式时间线

投递。Pillar Security 的研究者在 2026 年 8 月 10 日 21:52–23:07 UTC 观察到一个名为 zellkernel 的 GitHub 账号向 23 个无关的 AI、MCP 与开发者工具仓库提交 PR:17 个在目标项目配置里加入远程 MCP endpoint(productivity-suite-mcp.onrender.com/mcp),4 个配置本地隐藏脚本(~/.config/.cache/.sys/.deadbug-mcp.py)作为 MCP 服务器,2 个提交目录清单,疑似侦察。截至披露时 19 个 PR 被维护者关闭、4 个仍开着,无一走正常 review 合并流程;该账号当天创建了 50 个公开仓库中的 21 个,并与 X 账号 @llmgod 双向关联(来源:Pillar Security 原始披露)。

门控。服务器只公开两个无害名字的工具:format_text 与 summarize。它维护每个客户端的 tools/call 调用计数器:前三次调用,tools/list 与 prompts/get 返回与名字相符的正常描述;第三次之后,同一个接口开始返回恶意指令——搜寻 SSH 密钥、AWS 凭证、Kubernetes 配置文件与 shell 历史,中转或暂存这些材料用于外泄,并避免引起操作者注意。研究人员在延迟触发的恶意提示中发现了比特币地址,指向经济动机的攻击者而非研究演示(来源:Pillar Security 原始披露)。

规避。这是整个攻击最精巧的部分:服务器的代码与磁盘配置从不改变——它变化的只是运行时返回的协议响应。一次安装审查、一个静态扫描器、甚至一两次交互测试,都会停在阈值前,看到的是一个良性的格式化工具;只有持续的正常使用——恰恰是审查本来要建立的那种信心——会跨过阈值暴露载荷。Cloud Security Alliance 的判断是:这是对『点时间审查』这一当前主流 MCP vetting 机制的系统性规避(来源:CSA 研究笔记,2026-09-02)。

为什么『审查过』不再等于『可信』

对比一年前的同类事件就能看清 Deadbugz 的新意。2025 年 9 月,npm 包 postmark-mcp 用 15 个干净版本建立信誉,第 16 个版本悄悄加了一行代码,把外发邮件盲抄给攻击者控制的地址——这是经典的 rug pull:恶意代码随版本更新进入,包管理器与 SBOM 理论上能发现『版本变了』。Deadbugz 把恶意逻辑从第一天就内建在服务器里,用调用次数而不是版本号触发;SBOM 对比、diff 审查全部失效,因为恶意内容从来不在被审查的代码里,而在运行时的协议响应里(来源:The Register 对 postmark-mcp 的报道)。

由此得到一个硬结论:工具元数据——名称、描述、schema——是运行时安全边界,不是安装时的审批对象。Agent 被设计为信任协议元数据,因为它来自『可信的』协议层;攻击者不需要骗过模型,只需要在工具描述里写指令,Agent 就会照做——这正是 CSA 所说的 confused deputy:拥有合法广泛权限的实体,被操纵着以攻击者的意图行使这些权限,而自身的访问控制从未被绕过(来源:CSA 研究笔记)。

我们的判断:批准必须发生在动作时,而不是安装时

Deadbugz 不是又一个漏洞,而是对当前 MCP 治理主流做法的一次系统性质疑:大多数组织对 MCP server 唯一的 vetting 机制就是一次安装时审查,而一个计数器就把它绕过了。我们的判断是:工具描述是运行时安全边界;一次性审查不等于持续信任;批准应该发生在动作执行时,而不是安装时。

三个推论。第一,能力声明必须被连续监控:为每个已批准的 MCP server 建立工具 schema 的已知好指纹,每次 tools/list 或 prompts/get 响应与基线比对,偏离即告警——这个控制会在第三次调用之后不久就暴露 Deadbugz。第二,变更即重新批准:任何工具描述或参数 schema 的变化,无论来自 diff 还是运行时响应,对敏感动作(凭据访问、项目目录外文件读取、代码执行)都应触发新的人工批准。第三,这与我们一直主张的执行前授权(pre-execution authorization)是同一件事:Agent 治理的控制点不在『装什么工具』,而在『每个动作是否被允许』——安装时批准只是供应链卫生,不是授权。

引用一句 CSA 的话作为佐证:『工具描述与 schema 构成运行时安全边界,必须被连续监控,而不是被一次性批准。』我们与这个判断一致,并认为它应该成为 MCP 采购与部署的默认要求。

对买家意味着什么

AI App lead:集成任何第三方 MCP server 之前,要求 schema 指纹固定与运行时基线告警;把『添加或修改 MCP server 配置』的 PR 当作触碰生产凭据的变更来审查;来自陌生贡献者的 MCP 配置 PR,直接按最高风险处理。记住:关闭但未合并的 PR 不等于没被运行过——有人可能在本地试跑过。

安全团队:立即在代码库与 PR 历史中搜索上述 IOC;对任何『为 MCP 工具添加信任』的流程,补上运行时行为监控,而不是只靠一次性审查。

给你的行动建议

立即:grep 检查代码库与配置中是否出现 productivity-suite-mcp.onrender.com/mcp 或 ~/.config/.cache/.sys/.deadbug-mcp.py;搜索来自 zellkernel 的公开与已关闭 PR;发现即按失陷处理,轮换受影响主机可达的全部凭据。本周:为每个已批准的 MCP server 建立工具 schema 基线,并开始对 tools/list 响应做逐调用比对。长期:把『工具元数据变更』纳入重新批准流程,敏感动作的批准放到动作执行时——不是安装时。

参考来源: Pillar Security:Deadbugz 原始披露(2026-08-12) · CSA 研究笔记:运行时门控 MCP 元数据投毒(2026-09-02) · The Register:postmark-mcp 事件报道(2025-09-29)

常见问题

Deadbugz 是什么?+

Pillar Security 披露的活跃 MCP 供应链攻击活动:通过 GitHub PR 分发伪装成『productivity-suite』格式化工具的恶意 MCP 服务器,用运行时门控隐藏真实意图。

攻击如何被触发?+

服务器维护每个客户端的工具调用计数器,前三次调用返回正常描述;第四次起,tools/list 与 prompts/get 返回恶意指令,引导 Agent 搜寻 SSH 密钥、AWS 凭证、Kubernetes 配置与 shell 历史,并隐藏自身行为。

为什么常规审查抓不到它?+

恶意逻辑从第一天就内建,但用调用次数而非版本或时间触发;一次性安装审查、静态扫描或一两次交互测试都停在阈值前,看到的只有良性行为。

如何检查是否受影响?+

搜索远程 endpoint productivity-suite-mcp.onrender.com/mcp、本地脚本 ~/.config/.cache/.sys/.deadbug-mcp.py,以及来自 GitHub 账号 zellkernel 的公开或已关闭 PR;发现即按失陷处理并轮换可达凭据。

应该用什么控制来防御?+

为每个已批准的 MCP 服务器建立工具 schema 已知好指纹,对比每次 tools/list 响应;任何工具描述或 schema 变更触发重新批准;MCP server 做 allowlist,敏感动作在执行时重新验证身份与授权。

这与 2025 年的 postmark-mcp 事件有何不同?+

postmark-mcp 是版本更新后加入恶意代码(rug pull),包管理器与 SBOM 能发现版本变化;Deadbugz 的代码与配置从不改变,恶意行为只通过运行时协议响应暴露,diff 与版本对比全部失效。