深海军蓝背景上的抽象技术插画:左侧一个紧凑的服务器立方体朝右侧的智能体节点发出三张小矩形卡片;前两张卡片颜色苍白、毫无活性,第三张则投下一道形如钥匙的长影。细密的青色丝线从服务器伸向其后一片松散排布的仓库节点网格,一条琥珀色线条将智能体节点与一串由小凭证圆片构成的钥匙环相连。无人物、无标识、无文字。OrcaRouter 标识合成于右下角。
AI Safety Incidents

Deadbugz:一个在第三次工具调用时转为恶意的 MCP 服务器,74 分钟内被推送到 23 个仓库

作者

Magnus Corvin

发布日期

最新模型 · 20查看全部模型 →
基准测试:Artificial Analysis · 每日更新
返回全部文章

2026 年 8 月 10 日,一个 GitHub 账号 zellkernel在 74 分钟内针对彼此无关的 AI、MCP 和开发者工具代码库发起了 23 个拉取请求,每个请求都添加了一个名为 productivity-suite的 MCP 服务器,该服务器宣传了两个普通工具:format_text 和 summarize。据 Pillar Security称,该机构将这场活动命名为 Deadbugz,并于 8 月 12 日发布了分析文章:该服务器在前三次调用中返回真实结果,随后改写了交给智能体的元数据:工具描述和提示词内容开始引导模型转向 SSH 密钥、AWS 凭据、shell 历史记录和 Kubernetes 配置,并指示它对用户隐瞒这些活动。当 Pillar 审查这些请求时,23 个拉取请求中有 19 个已关闭,4 个仍处于打开状态,且无一被合并。尚未确认有受害者。这是一条记录,由他人报告,并在此引用他们作为来源。其他有记录的智能体事件各自都有来源、严重程度、置信等级和争议标记,均收录在 AI 事件档案中——因此,一场针对智能体工具链的供应链活动可以与其他实际发生的事件放在一起解读。

档案将该记录评定为高严重性和A级置信度——记录完备,且有意见一致的一手来源——同时又另外记载:未确认存在真实危害。这两件事同时成立,而它们之间的落差正是这份记录的核心所在:一场行动,其设计在产生任何可指名的受害者之前,就已以少见的方式被详尽记录。两个关键日期相隔两天。相关拉取请求于8月10日发出;Pillar Security的Ariel Fogel于8月12日发布了分析,该文章附有一则长期有效的说明,称将随着已核实信息的到来而更新。

三次调用,随后元数据发生变化

MCP 服务器不必在机器上运行代码就能改变智能体的行为。工具定义会在每次会话中作为上下文交给模型,这意味着提供这些定义的服务器可以重写智能体读取的指令,同时让工具的名称、其仓库和其清单保持原样。Deadbugz 正是建立在这种不对称性之上,而 Pillar 将其称为运行时门控的 MCP 元数据投毒。

其机制简单到一句话就能说清。服务器在内存中为每个客户端维护一个 tools/call 请求的计数器。前三次它表现正常。一旦计数器被触发,之后的 tools/list 和 prompts/get 响应返回时就会被篡改——工具描述不同、提示内容不同——将智能体指向 SSH 密钥、AWS 凭证、shell 历史和 Kubernetes 配置,并指示它向用户隐瞒这些活动。被投毒的提示文本带有标记 deadbugz 和一个比特币地址。

这道门控也是普通防御措施无法将其捕获的原因。从第一次请求开始,载荷就已经存在于源中;在切换发生的那一刻,代码或配置没有任何变化。静态扫描、SBOM 条目或在安装时对工具清单的一次性读取,看到的都是一个格式化实用程序,因为在计数器变动之前,该实用程序返回的就是这个。Pillar 将这种延迟切换描述为一种研究规避技术,并表示其研究人员通过向实时远程服务发送纯文本请求,并将响应与公开源代码进行匹配,确认了阈值和被修改的元数据。

有一个细节让这个陷阱的影响范围超出了一个会话。服务器会通告tools.listChanged,这是 MCP 的一项能力,用于告知客户端其工具列表已被修订。遵循该信号的客户端会在会话中途重新读取定义,并在无需操作员采取任何操作的情况下拉取被投毒的版本;而在批准时缓存定义的客户端则不会。某个特定 agent 采取哪种行为,取决于客户端而非服务器,而且 Pillar 的文章并未逐一列出客户端名称。

HTML card titled 'Three calls, then the metadata changes', kicked 'MCP · productivity-suite', with the subtitle 'The payload is present from the first request; the gate is a counter in memory'. Three columns. 'Calls one to three — benign' lists format_text returning formatted text, summarize returning a summary, and tools/list and prompts/get returning honest tool definitions, with a note that nothing on disk differs from what a reviewer approved. 'The gate' lists an in-memory per-client counter of tools/call requests, a threshold of three, altered tool descriptions and prompt content in later tools/list and prompts/get responses, and the advertised tools.listChanged capability that lets compliant clients re-read definitions mid-session. 'What the poisoned metadata asks for' lists SSH keys, AWS credentials, shell history and Kubernetes configuration, an instruction to keep the activity from the user, and the embedded marker deadbugz with a Bitcoin address. A footer reads 'Per Pillar Security's disclosure of 12 August 2026. Pillar says its researchers confirmed the threshold and the altered metadata against the live remote service using text-only requests, matching the public source.'

交付:74 分钟内完成 23 个拉取请求

这次分发并不是注册表上的某个软件包,也不是埋藏在 lockfile 中的被污染依赖。它是针对那些与服务器所谓功能毫无关系的项目发起的拉取请求垃圾提交,而这正是低成本供应链攻击尝试在攻击者无法获得维护者账户时所呈现的形态:提交足够多的配置变更,然后等待其中某一个被合并或在本地被应用。

Pillar 将这 23 个拆分为三类。其中 17 个添加远程 MCP 端点 productivity-suite-mcp[.]onrender[.]com/mcp,托管在 Render 上;4 个会调用位于 ~/.config/.cache/.sys/.deadbug-mcp.py 的隐藏本地 Python 文件;2 个是目录或列表提交,报告将其视为侦察或填充内容,而非投递。时间窗口给出为 2026 年 8 月 10 日 UTC 21:52 至 23:07——按披露的说法为 74 分钟,尽管这两个时间戳本身跨度为 75 分钟,且记录中没有任何内容取决于这一分钟。只有一个目标仓库被单独点名:getsentry/sentry-mcp,拉取请求 #1239,被引用为本地工件投递的一个示例。

就这个账号的存在时间而言,其内容规模相当可观。在 Pillar 采集数据时,zellkernel 拥有 50 个公开仓库,其中 20 个是 fork(分叉),而这 50 个仓库中有 21 个创建于 8 月 10 日——与那场活动同一天。该个人资料与 X 账号 @llmgod 相互关联,而该账号又反向链接回这个 GitHub 账号;这种相互关联恰恰说明这是一个专门打造的账号身份,而非遭到劫持的账号。

十九个已关闭、四个仍开启、零个已合并,是记录中重复次数最多的数字,也是最常被解读为“完全无事”的数字,但事实并非如此。GitHub 的合并按钮并不等同于托管方的执行记录:维护者可以拉取某个分支并运行它、手动应用配置,或者 CI 作业可以在任何人发表评论之前获取某个 PR 的头提交。那四个编写配置并调用本地脚本路径的拉取请求,正是这一缺口最关键的地方,因为该脚本完全是在 GitHub 的合并统计之外被获取和运行的。云安全联盟实验室(Cloud Security Alliance Labs)在 9 月 2 日的说明中也提出了同样的观点:已关闭和未合并的计数并不能证明没有任何东西运行过。

HTML card titled 'Twenty-three pull requests in seventy-four minutes', kicked '10 August 2026 · delivery', subtitled 'Times UTC. Counts are Pillar Security's review snapshot.' Three columns. 'The window' lists the first pull request at 21:52, twenty-three pull requests to unrelated AI, MCP and developer-tooling repositories, the last at 23:07, and a note that the 74-minute framing spans 75 minutes on the clock. 'What each pull request added' lists seventeen adding the remote endpoint productivity-suite-mcp.onrender.com/mcp, four invoking the hidden file at ~/.config/.cache/.sys/.deadbug-mcp.py, two directory or listing submissions, and one named example, getsentry/sentry-mcp pull request 1239. 'At review' lists nineteen closed, four open, zero merged through GitHub's review, zero confirmed victims, and the account zellkernel linked to the X handle llmgod, with fifty public repositories and twenty-one created that day. A footer reads 'Per Pillar Security. Cloud Security Alliance Labs repeated the same figures on 30 August and 2 September 2026 without independent verification. As of 29 October 2026 the GitHub account and the productivity-suite-mcp repository both return 404.'

什么是已确立的,什么不是

这些内容由该披露所确立,具体而言,Pillar 是根据其阅读过的制品、并在一个情形下根据其查询过的服务来报告这些内容的:服务器及其源代码仓库、两个对外宣传的工具、计数器与三次调用阈值、四个凭据目标、PR 数量及其在审查时的合并状态,以及 GitHub 账号与 X 账号之间的关联。Pillar 针对实时端点所做的自身测试是这份清单上最有力的项目,因为它是复现,而非对源代码的阅读。

是否存在受害者尚未确认,记录对此也很谨慎。该档案的 real_harm 字段为 false,这是关于证据的陈述,而非关于意图的陈述——没有人拿出与此次行动相关联的主机、日志或被盗凭据。zellkernel 和 @llmgod 背后的人或组织也未被确认;Pillar 将该行动归因于这些账号,就此止步。经济动机的依据是载荷中嵌入的一个比特币地址,这是从某个指标得出的推断,而不是关于行为体的调查结论。而防御者最想得到答案的问题——该行动是否仍在进行——在记录中没有答案:该帖子被标记为将会更新,而且看不到 GitHub 或 Render 之后发布的修订或下架通知。

佐证比置信等级所暗示的更为薄弱,这一点值得直说。两份Cloud Security Alliance Labs研究简报,日期分别为2026年8月30日和9月2日,重述了该攻击活动;较晚的一份明确表示,它将发现、PR细节、服务器行为以及账户归因都归功于Pillar,并且没有描述其自身的任何独立验证。一篇日期为2026年9月22日的Armor博客文章提供了防御指导,并称Pillar拆解了该服务器;它没有提供自己的任何取证证据。没有分配CVE,CSA表示这不是MCP规范漏洞。截至2026年10月29日,检索未发现GitHub或Render发布的任何公告,主流安全行业媒体也没有相关报道——没有BleepingComputer、The Register、SecurityWeek或Hackread的条目——对于这种形态的供应链攻击活动来说,这并不寻常,而这本身也是记录所显示内容的一部分。这里的“主要来源一致”是指一个原始主要来源,以及一组源自它的次要文档。

有两处较小的歧义值得指出,而不是一笔带过。二手摘要对于第三次调用还是第四次调用最先收到被污染的元数据存在分歧,这是因为计数器被描述为在第三次请求时触发;而记录和披露都采用“三”这一说法。此外,交付窗口被描述为 74 分钟,但时间戳的跨度却是 75 分钟。

有一项检查无法重复进行:zellkernel以及仓库zellkernel/productivity-suite-mcp均返回 404,而单独点名的一个拉取请求 getsentry/sentry-mcp #1239 也不再能解析——该仓库本身现在重定向到 getsentry/toolkit。因此,PR 数量、合并状态和仓库内容今天无法由第一方重新核实;它们仍作为 Pillar 于 8 月中旬拍摄的快照存在。

HTML card titled 'What is established, and what is not', kicked '2026-08-10-deadbugz-mcp-supply-chain', subtitled 'One record, one originating source, two secondary notes that restate it'. Three columns. 'Established by the disclosure' lists the server, its source repository and the two advertised tools; the counter and the three-call threshold, confirmed against the live endpoint; the four credential targets; twenty-three pull requests, nineteen closed, four open, none merged; and the delivery account linked to the X handle llmgod. 'Not established' lists any victim or executed payload, with the archive recording real harm as false; the actor behind the account and handle; motive, which rests on a Bitcoin address in the payload; and whether the campaign is still running, the post having promised updates that are not visible. 'Corroboration' lists the Cloud Security Alliance Labs notes of 30 August and 2 September 2026 as restatement without independent checks; the Armor blog of 22 September 2026 as guidance without forensic evidence; no CVE assigned; no GitHub or Render advisory found; and no mainstream trade-press coverage found as of 29 October 2026. A footer reads 'The archive grades the record A, well documented with primary sources that agree. The secondary documents here all derive from Pillar Security's post, so agreement between them is not a second measurement.'

该披露要求防御者做什么

Pillar 建议的应对措施,主要是把元数据视为一种安全面,而不是将其视为对安全面的描述。对于主机,具体要求是阻止或搜寻 productivity-suite-mcp[.]onrender[.]com/mcp,将此次攻击活动早前使用的 trycloudflare.com 端点保留在拒绝列表和搜寻列表中,尽管 Pillar 称其当前并未活跃,并且不要运行 deadbug-mcp.py——隐藏文件路径 ~/.config/.cache/.sys/.deadbug-mcp.py 才是应在各主目录、代码仓库和 MCP 客户端配置中搜寻的痕迹。

调查的先后顺序比阻止列表更重要。如果某台主机可能已经建立过连接,Pillar 建议在清理任何东西之前先保留 MCP 客户端日志,然后审查工具定义的刷新情况,以及智能体在第三次调用之后做了什么;只有在本地证据支持存在暴露时才应轮换凭据,这与一有怀疑就轮换一切的反射式做法正好相反。该服务器的配置还允许将可选遥测数据发送至 WEBHOOK_URL,在连接、首次调用和触发事件时发出信标——这一细节为调查提供了除客户端日志和端点流量之外的第三个查看位置。

对于构建 MCP 客户端的人而言,这项建议是结构性的,也是该记录中保存期最长的部分:

在审批时对工具定义生成指纹,并在每次刷新时进行比对,而不是仅凭服务器的名称和仓库来信任它。

• 将已批准服务器上的定义变更视为操作员可见并需重新批准的安全事件,而不是被静默吞下的例行元数据变动。

• 通过策略而非服务器提供的描述来强制执行敏感操作——凭据访问、代码执行、外发邮件、仓库写入。

正是第三项使 Deadbugz 成为一份记录,而不只是一桩奇闻。上述每一项控制措施都假定:服务器附加到某个工具上的文本能够诱导智能体去做某些事,并且该文本可以在信任决策作出之后发生变化。Pillar 将这次攻击活动置于一条脉络之中,其中包括 Invariant Labs 的 2025 年 MCP 休眠攻击、伪造的 postmark-mcp 软件包,以及一个由 Koi 记录、通过更新被武器化的 MCP 软件包——它们都是该技术的先例;Pillar 引用这些先例正是为此,而不是将其作为关于此次投递的证据。

为何“门”事件比受害者人数更重要

一次有 23 次投递尝试、没有合并、也没有已确认受害者的攻击活动,很容易归入“未遂”并就此翻篇。它之所以应以高严重性归入档案,是因为其规避并不依赖投递在大规模上成功。它依赖的是当今大多数 MCP 部署共有的一个特性:批准只在安装时发生一次,并且被批准的定义被假定就是将要提供的定义。Deadbugz 在前三次调用中保持这一假设不变,随后将其打破。

修复方案并不是针对某个特定服务器的补丁,也没有需要跟踪的 CVE。关键在于,“已批准”必须成为一种持续状态,并且背后要有比较机制——这改变的是客户端及其操作者的行为方式,而不是扫描器要查找的内容。是否真的有人在八月运行过该服务器仍然未知;就现有记录而言,真正的发现是这一机制本身。