FlawOpen

flawopen.com/Incidents/deadbugz-mcp-delayed-metadata-supply-chain-campaign-august-2026

● Pillar Security / MCP ecosystem · CWE-829 (editorial mapping; no CVE assigned) · 2026-08-10 · 中危
安全研究 · FlawOpen

Deadbugz:MCP 工具元数据在获批后发生变化

Pillar Security 记录了一场 MCP 供应链活动:服务器在三次正常调用后更改元数据。其审查未发现通过 GitHub PR 流程合并的请求;报告未记载后续入侵。Cloud Security Alliance 指出,无法充分了解目标是否独立在本地运行过该服务器。[1], [3]

💡 通俗易懂的原理解析 (ELI5)

想象你批准一名承包商,因为他的证件写着无害工作。三次日常送货后,证件悄悄变了,开始要求进入上锁房间。危险在于大楼仍信任旧审批。MCP 客户端必须发现服务器更改了已批准工具的说明。[1]

核心概念与专有名词

MCP
AI 应用通过该协议发现并调用服务器提供的工具。[5]
工具元数据
工具名称、说明和输入架构;客户端可能把它们作为上下文交给模型。[5], [1]
运行时延迟变更
达到交互次数阈值后才出现的行为;Pillar 报告称阈值为三次调用。[1]
供应链投递
通过可信开发流程(例如 pull request)引入依赖或配置。[1]
CWE-829
编辑分类:功能来自客户端信任控制范围之外的服务器。未分配 CVE 或 CVSS。[1], [3]

框架映射

  • 本指南所述弱点的 CWE 参考: CWE-829

事件演进时间线

2026-08-10

Pillar 发现 23 个相关 pull request,在 74 分钟内创建;审查时没有一个通过 GitHub PR 机制合并。[1]

2026-08-12

Pillar 发布技术报告,说明三次调用后的元数据变化及相关指标。[1]

2026-10-08

OWASP GenAI 项目在 2026 年第三季度综述中纳入 Deadbugz;这说明受到关注,不代表已确认入侵或搜索量。[2]

攻击执行流程分解

步骤 1

有人提出配置变更

pull request 将远程或本地 MCP 服务器配置加入 AI 项目。Pillar 审查了 17 个远程 endpoint 变更、4 个隐藏本地脚本引用和 2 个目录/列表提交。[1]

步骤 2

初次审查只看到普通工具

服务器最初提供文本格式化和摘要工具。Pillar 表示,短暂测试可能只得到这些无害元数据。[1]

步骤 3

正常使用越过触发阈值

服务器按客户端统计调用次数。三次调用后,后续 tools/list 与 prompts/get 响应会改变。[1], [5]

步骤 4

代理收到不可信指令

这些指令试图引导已连接的代理查找敏感本地信息并隐藏活动。该活动描述并未证明发生了入侵。[1], [3]

步骤 5

审批必须绑定精确元数据

客户端应为已批准工具定义计算指纹,发现差异时暂停并要求操作员复核。文件、凭证和网络权限应由独立策略强制执行。[1], [4], [5]

源代码对比:漏洞与安全实现

报告描述的是元数据投毒与 pull request 投递,不是 MCP 规范中的 CVE。若客户端在初次批准后仍信任服务器可变的描述,就会产生风险。Pillar 将活动归因于一个公开 GitHub 账户;本文将其表述为 Pillar 的归因,而非已核实的现实身份。Pillar 表示其审查的 PR 当时没有通过 GitHub 的 PR 流程合并,也未确认后续入侵。关联的源码仓库目前返回 404,因此技术事实依据 Pillar 发布的技术分析,而不是本次重新独立检查源码。Python 示例是客户端防护策略示意,不是可直接替换 MCP 库的代码。CWE-829 是编辑分类;没有 CVE 或 CVSS。 适配器必须在收到 MCP 变更通知后刷新数据,并同时纳入 tools/list 和 prompts/get;metadata_snapshot 是示意用适配器方法,不是 MCP SDK API。只有操作员审核后才能生成 approved_digest。 快照必须包含所有相关服务器元数据,包括 tools/list 定义以及已批准提示的完整 prompts/get 内容。执行前重新获取,若不匹配则停止操作。此检查无法发现服务器行为变化或检查与使用之间的变化,因此仍需独立的操作权限控制。[1], [4], [5]

存在漏洞的实现
def agent_metadata(session):
    # 适配器将服务器当前的工具和提示作为 JSON 数据返回。
    return session.metadata_snapshot()
加固后的安全修复
import hashlib
import hmac
import json

def fingerprint(snapshot):
    normalized = dict(snapshot)
    for key in ("tools", "prompts"):
        normalized[key] = sorted(
            snapshot[key],
            key=lambda item: json.dumps(item, sort_keys=True, separators=(",", ":")),
        )
    canonical = json.dumps(normalized, sort_keys=True, separators=(",", ":"))
    return hashlib.sha256(canonical.encode()).hexdigest()

def agent_metadata(session, approved_digest):
    current = session.metadata_snapshot()
    if not hmac.compare_digest(fingerprint(current), approved_digest):
        raise PermissionError("MCP metadata changed; require operator approval")
    return current

工程与系统安全加固清单

参考来源