WARDEN 项目扫描公共 MCP 注册表服务器,发现59%首次请求即失败,主要为认证墙、TLS 错误或服务下线;仅4台存在真实恶意工具定义。
你的 MCP 服务器告诉 agent 它的工具能做什么。agent 相信它。
这句话就是攻击面——也是为什么没人知道公开注册表中实际有多脏。所以我们做了测量。
在发布 @aimarket/warden 0.3.0 几个小时后,我们用 MCP 安全防火墙扫描了官方注册表中每一个能够合法触达的公共服务器。未执行任何第三方代码。每条工具定义均来自服务器自身的 tools/list 返回。
完整调查报告(方法、局限性、JSON 语料):github.com/alexar76/warden/blob/main/docs/mcp-survey.md 落地页:warden.modelmarket.dev
注册表大部分不可达

如果你在基于公共注册表构建 MCP 客户端,要做好 59% 首次连接失败的心理准备——认证墙、TLS 错误、主机消失、协议不匹配。
我们只使用了 streamable-http(20 秒超时,一次尝试)。37 个 sse 服务器被跳过。awesome-lists 中的所有 stdio 服务器均不在范围内:触达那些意味着下载并运行陌生人的代码。
WARDEN 屏蔽了 50 台服务器。其中 4 个经证实有效。

这四个被屏蔽的案例描述了确实会将秘密材料在模型上下文中传递而未给出命名的工具:
一个财政工具,其 schema 接收 signer_private_key("签名者 EOA 私钥,0x…")。
一个 agent-payments 工具,通过工具通道"恰好一次返回其私钥"。
一个身份工具,其说明文字告诉模型读取 credentials.json 并写入 JWK private_key 文件。
一个托管数据库工具,带有文档化的 pvkPassword 参数。
这是 1,108 个扫描对象中的 4 个。以下是其余 46 个——我们的扫描器出错了。
我们公布这些误报,因为一个对正常服务器也报错的工具投毒扫描器不是谨慎,而是会被卸载的扫描器。
极性盲——我们最大的缺陷

TOOL_DEF_SECRET_REQUEST 匹配了名词短语 private key。它没有读取周围的句子。
这些都在 critical 级别被屏蔽——整个服务器被拒绝:
Never send a private key: none is needed and the request is refused if one is present.(绝不要发送私钥:不需要且如果存在则请求会被拒绝。)—— 一个 DANE/TLSA 记录生成器
Use this to import your own public key so you can SSH into instances. The private key never leaves your machine.(用这个导入你自己的公钥,这样你就能 SSH 登录到实例。私钥永远不会离开你的机器。)—— 一个云实例管理器
…does NOT confirm the certificate matches any private key.(…不确认证书是否匹配任何私钥。)—— 一个证书检查器
一条在单个服务器上 377 个工具中重复的样板话被计为 377 条发现。我们按服务器计数,不按复制粘贴次数。
同一语料库中的其他误报家族:
javascript: in examples — image-API 文档,不是 XSS 载荷。
system prompt 作为领域词汇 —— 描述攻击面的安全工具。
波斯语 ZERO WIDTH NON-JOINER —— 必需的拼写规范,被标记为"隐藏 Unicode"。
威胁情报通配符 —— funds 出现在 refunds 内,drain 出现在 anti-drainer 扫描器内。
advisory 层级按设计运作:3,472 条 advisory 命中未屏蔽任何东西。在规则集 v1 下,其中很多会对正常服务器直接拒绝。
规则集 v4 —— 在同一组 1,108 台服务器上重新测量

我们加入了 guards —— 上下文检查,决定一条正则匹配是否就是规则要找的那个东西(极性、提及、检测、uri、zeroWidth、…)。规则集 v4 在 @aimarket/warden 0.4.0 中发布。
每一条真实发现仍然被屏蔽。回归测试套件建在这份语料库的真实文本之上——没有人会凭空写出"the private key never leaves your machine"或者用 U+200C 拼写波斯语。

npm install @aimarket/warden
import { Warden, ThreatFeed, silentLogger } from "@aimarket/warden";
const warden = Warden.create({
policy: { blockAtSeverity: "high", allowUnknownServers: false, pinToolDefs: true },
threatFeed: new ThreatFeed({}),
store: { getPin: async () => null, putPin: async () => {} },
log: silentLogger(),
});
const verdict = await warden.vet(serverRef, tools);
if (!verdict.allow) throw new Error(`blocked: ${verdict.decidedBy}`);
vet() 不执行任何网络 I/O,除非你显式加载了可选的签名威胁情报获取。除 node:crypto 外零运行时依赖。
定义,不是实现。工具的说明文字干净,并不意味着调用时不会泄露。静态扫描看不到那个。
没有真值标签。我们可以说 46 个中的 50 个屏蔽是错的;但我们无法统计漏报。
认证限制服务器缺失。1,215 台服务器因缺少凭证而拒绝 —— 语料库偏向开放/ hobby 级别。
一次快照。2026-08-24。 pinning 存在正是因为描述会在之后发生变化。
复现步骤:scripts/mcp-survey/ · 聚合 JSON 在 docs/data/mcp-survey-2026-08-24.json
Repo:github.com/alexar76/warden(MIT)
npm:@aimarket/warden
调查报告:docs/mcp-survey.md
更早的 Dev.to 文章介绍该防火墙本身:Your MCP server might be a prompt injection attack
如果你从公共注册表运行 MCP 工具,在它们到达模型之前先审查定义。而如果你在构建扫描器,公布你的误报——这个数字决定了是否有人会启用它。