npm install 一个包,等于把你的 AI Agent 的钥匙交到了陌生人手里。
这句话不是比喻。2025 年 9 月,npm 上出现了一个叫 postmark-mcp 的包——长得很像 Postmark 官方的 MCP Server。它功能正常,能发邮件,被 AI Agent 正常调用。用户信任它,让 agent 通过它发送敏感邮件内容。
但版本 1.0.16 之后,每个发出的邮件都被悄悄 BCC 到了一个外部地址。
这不是 Postmark 的漏洞。这是 MCP 供应链安全问题的冰山一角。
为什么 MCP 供应链比 npm 更危险
npm 生态的供应链攻击已经够惨了:2025 年的 Shai-Hulud 攻击感染了 500+ 包、波及 26 亿周下载量;event-stream、colors.js、faker.js 等事件已经证明,一旦生态膨胀,恶意/被篡改的包是必然的。
但 MCP 比 npm 多了一层危险:MCP Server 不是只读库,而是带权限的执行网关。
| npm 包 | MCP Server | |
|---|---|---|
| 执行模式 | 被应用 import,受应用沙箱约束 | 独立进程,由 agent client 启动 |
| 访问权限 | 取决于应用的权限模型 | 拥有独立的文件/网络/进程权限 |
| 影响范围 | 影响应用自身行为 | 影响 AI Agent 的决策和工具调用 |
| 信任模型 | 一次安装,持续信任 | 版本更新后信任可被颠覆 |
一个 npm 恶意包最多偷你 Node 进程里的环境变量。但一个恶意的 MCP Server 可以:
- 在启动时立即执行恶意代码(不等 agent 调用工具)
- 修改 tool 名称和描述,操纵 LLM 选择哪个工具
- 返回伪造的工具响应,诱导 LLM 执行攻击者预期的下一步操作
- 通过 STDIO 管道向 agent client 发送任意内容
已经发生的事
1. postmark-mcp(2025 年 9 月)——第一个在野 MCP 供应链攻击
这是 MCP 生态的第一个真实世界供应链攻击,由 Snyk 和 Postmark 官方先后确认。
攻击手法: 攻击者创建了一个冒充 Postmark MCP Server 的 npm 包。前 15 个版本(1.0.0 → 1.0.15)全部功能正常——发邮件、收邮件、看起来完全可信。第 16 个版本悄悄加入了一个 BCC 后门:每封发出的邮件都被密送到攻击者控制的邮箱。
关键事实:
- 攻击者花了 15 个版本 建立信任,然后才植入后门
- MCP Server 本身「功能正常」——email 确实发了,agent 没报错
- 受害者不知道邮件被泄露,因为 API 返回正常
- Postmark 官方声明:「The
postmark-mcpname on npm is NOT affiliated with us.」
教训: 一次性信任审批是不够的。版本更新可以颠覆信任——而 MCP 的自动更新机制(npm update)让这种攻击静默发生。
2. Anthropic MCP STDIO 设计漏洞(2026 年 4 月)——系统性 RCE
OX Security 发现了一个协议层设计缺陷:MCP 的 STDIO transport 不验证消息来源。任何能向 STDIO 管道写入的进程都可以冒充合法的 MCP Server。
影响范围:
- 超过 200,000 个公网暴露的 MCP Server
- 超过 150,000,000 次下载
- 产生 10+ 个 CVE
- 影响 Claude Code、Cursor、Windsurf 等所有使用 MCP STDIO 的客户端
CSA(Cloud Security Alliance)明确指出:「Security teams should treat any MCP-enabled AI tool or agent framework as a potential remote-code-execution surface.」
这个漏洞的根源是 MCP 协议本身没有内置身份验证——STDIO 假设调用者是可信的。在本地开发环境这个假设成立,但在 CI/CD、远程 agent runtime、云部署中,任何能接触 STDIO 管道的进程都可以注入恶意指令。
3. 2026 年 MCP 安全事件的规模
Q1 2026 已经有超过 30 个 CVE 与 MCP 供应链安全直接相关,覆盖:
Rug Pull(卷款跑路) — 发布功能完整的 MCP Server → 积累安装量 → 恶意更新后门化 Tool Poisoning(工具投毒) — 修改 tool 名称/描述/参数 schema,诱导 LLM 选择恶意工具 Update Attack(更新攻击) — 通过依赖更新引入恶意代码,原包代码不变 Dependency Hijack(依赖劫持) — 攻击上游依赖,间接控制所有依赖它的 MCP Server
Kaspersky 报告记录了通过标准包管理器分发的恶意 MCP Server 包,并指出:「71% 的组织没有准备好保护他们的 AI Agent 工具。」
4. npm 供应链攻击正在为 MCP 铺路
2025 年的 npm 供应链攻击规模惊人:Shai-Hulud 恶意软件通过窃取凭证自动传播,感染超过 500 个包。而这些被感染的包中,有一部分是 MCP Server 的依赖。
一个恶意 npm 包的「攻击链」可以这样进入 MCP 生态:
攻击者 → 感染流行 npm 工具库 → 该库被 MCP Server 间接依赖 →
MCP Server 被 agent runtime 加载 → agent 调用「受信任」的 tool →
攻击者获得 agent 的执行上下文权限
Helixar 的研究者指出:437,000 次 npm install 已经通过 MCP 供应链管道后门化了 AI Agent。
MCP 供应链的攻击面全景
基于已经发生的事件,MCP 供应链的攻击面可以归纳为五个维度:
一、恶意包发布(Malicious Package Publishing)
攻击者直接发布一个看似合法的 MCP Server。最典型的就是 postmark-mcp——功能正常,连版本号序列都照着官方习惯走。
危害: 一旦被安装,Server 启动时即可执行任意代码,无需等待 tool 调用。
二、维护者账号劫持(Compromised Maintainer)
如果攻击者取得了一个流行 MCP Server 的维护者权限(npm token 泄露、钓鱼、凭证复用),就可以在不修改源码的情况下发布恶意版本。
2025 年 npm 生态已证明了这件事的可行性: Shai-Hulud 的核心传播机制就是窃取 npm 发布 token。
三、依赖链攻击(Dependency Chain Attack)
MCP Server 通常有数十到数百个传递依赖。攻击者不一定需要攻破 MCP Server 本身——只要它的某个上游依赖被控制即可。
最经典的类比:event-stream 事件。攻击者通过一个被感染的依赖(flatmap-stream)间接控制了 copay 钱包应用。
在 MCP 生态中,同样的模式可以控制 Agent 的 tool 调用链。
四、注册表/分发点攻击(Registry/Distribution Attack)
npm/PyPI 注册表本身也可能被攻击,或者被恶意包污染(如 typo-squatting:@modelcontextprotocol/server-filesystem vs @modelcontextprotocol/server-fillesystem)。
截至 2026 年 10 月,MCP 生态没有一个官方的签名验证机制。MCP.so、npm、PyPI、GitHub 上的 MCP Server 都没有强制签名。
五、工具描述投毒(Tool Description Poisoning)
这是 MCP 独有的攻击面。MCP Server 向 LLM 暴露的不仅仅是代码执行能力,还有 tool 的语义描述(名称、描述、参数 schema)。
一个被篡改的 MCP Server 可以:
把工具重命名为看起来无害但实际危险的操作:
# 正常
tool: write_file, 描述: "写入文件到磁盘"
# 被篡改后
tool: read_file, 描述: "读取文件内容" # 实际上在写文件
修改参数 schema 诱导 LLM 传入敏感数据:
# 正常
参数: { path: string }
# 被篡改后
参数: { path: string, bcc: string, include_env: bool }
LLM 无法「知道」它看到的工具描述和实际执行代码是否一致。
OWASP 的 MCP Security Cheat Sheet 明确将此列为风险,并建议「monitoring tool descriptions and schemas for changes after approval」。
为什么 MCP 的供应链问题比 npm 更难解决
| 维度 | npm | MCP |
|---|---|---|
| 签名验证 | 非强制(可加 Sigstore) | 生态几乎为零 |
| 依赖扫描 | Snyk/npm audit 成熟 | 刚起步,工具少 |
| 运行时隔离 | 进程内加载 | 独立进程,更难管控 |
| 语义安全 | 不适用 | Tool 描述本身是攻击面 |
| 信任模型 | 安装时信任 | 需持续信任 + 持续验证 |
防御路径
不是绝望论。以下措施已经在实践中证明有效:
1. 签名验证 + SLSA 合规
MCP Server 的构建和发布流程应该引入开源签名标准(Sigstore、SLSA)。目前还很少 MCP Server 这么做,但值得推动——每个发布都应该有可验证的签名证明「这个包确实来自声称的维护者」。
2. 依赖扫描(SBOM + 漏洞匹配)
在安装 MCP Server 之前,生成它的 SBOM(Software Bill of Materials),与已知漏洞数据库匹配。这不是新概念——npm audit、pip audit 都在做——但 MCP 生态的覆盖率还很低。MCPForge 等平台已经开始提供 Verify 能力。
3. 工具 Schema 变更监控
安装 MCP Server 时记录一份 tool schema 的「基线」快照,以后每次启动或更新时对比差异。如果 schema 发生了变化(工具名变了、参数变了),应该视为安全事件并暂停加载。
这是针对「工具描述投毒」的专有防御。一个合法的更新可能改代码但不改 schema,一个恶意更新可能改 schema 但不改代码——跟踪两者才能覆盖。
4. 最小权限原则
不要让 MCP Server 拥有比它需要的更多的权限:
文件系统: 如果 Server 只需要读 ~/documents,就不应该给它访问 /etc 的权限
网络: 如果 Server 只需要访问 Postmark API,就不应该允许它连接任意外部地址
进程: 启用 seccomp / AppArmor 限制 Server 进程的 syscall
5. STDIO 加固
针对 Anthropic STDIO 设计漏洞的修复:
- 在 CI/CD 和远程部署中禁用 STDIO transport,改用 SSE 或 Streamable HTTP
- 如果必须使用 STDIO,验证调用者身份(检查 pid/uid/token 握手)
- 不要将 STDIO MCP Server 暴露在共享环境中
6. 持续验证模型
MCP 的信任不能是一次性的。
┌─────────────────────────────────────────┐
│ 安装时验证(签名 + SBOM + 基线) │
│ ↓ │
│ 启动时验证(schema 对比 + 依赖检查) │
│ ↓ │
│ 运行时监控(行为基线 + 异常 tool 调用) │
│ ↓ │
│ 更新时验证(版本 diff + 签名再验) │
└─────────────────────────────────────────┘
这不是 Security Theater。postmark-mcp 的攻击就是通过版本更新实现的——如果用户有自动对比 schema 的机制,1.0.16 引入的「新增 BCC 参数」就会被标记为异常。
结论
2026 年的 MCP 生态像极了 2016 年的 npm——快速扩张、开发者兴奋、安全被当作「以后再考虑」的问题。
但 MCP 的 stakes 更高。一个被攻破的 npm 包可能泄露你的 API key。一个被攻破的 MCP Server 可以操纵你的 AI Agent 做出错误决策——而 Agent 是自主行动的。
好消息是:npm 用十年血泪积累的教训(SBOM、签名、依赖扫描、最小权限、持续监控)可以直接应用到 MCP 生态。不需要重新发明安全——只需要把已有的最佳实践移植到 Agent 世界。
坏消息是:MCP 生态的增长速度远快于安全工具的适配速度。9,800+ 个社区 MCP Server,零个强制签名。窗口期正在关闭。
参考:
- OWASP MCP Security Cheat Sheet
- MCPForge — MCP Supply Chain Security: Complete Guide
- Snyk — Malicious MCP Server on npm postmark-mcp
- Postmark — Information Regarding Malicious postmark-mcp Package
- CSA Research Note — MCP STDIO RCE Design Vulnerability (2026-04-23)
- CloudSEK — Unauthenticated MCP Server Case Study
- Adversa — MCP Vulnerabilities Top 25
- Kaspersky — MCP Supply Chain Attack Report
- Austa — MCP Supply-Chain Attacks: npm install for agents