你连接的每一个 MCP 服务器都会把一段 tools/list 响应——一份由服务器构建者编写的 JSON 文档——未经审查就直接送入你的模型上下文。把那段响应粘贴进 VeriSwarm 的扫描器,几秒钟内就能得到 11 项确定性检测结果:工具投毒、域名仿冒(typosquatting)、模式(schema)篡改、rug-pull 模式、提示词注入、过度权限、模型误绑定、上下文伪造、隐蔽通道、不安全的内存引用,以及请求头注入。全程没有任何 LLM 来评判你的工具——只有始终返回同一判定结果的模式与结构分析。
MCP 工具的元数据承载着关键作用。模型会根据描述文本(而非背后的代码)来决定调用什么、如何调用。一段被投毒的描述甚至不需要真正入侵任何东西;攻击完全发生在模型的推理过程内部。MCPTox 基准测试针对 45 个真实 MCP 服务器和 353 个真实工具进行了验证,测得攻击成功率超过 60%,最高达到 72%。靠肉眼阅读工具描述,超过第一台服务器就无法扩展,更经不起 rug pull 的考验——一台在你审查期间表现干净、却在下一次版本更新时改头换面的服务器。
这些检测覆盖了扫描器最初构建时针对的风险类别——最容易出现在被投毒或粗心编写的工具定义中的那些。
隐藏在描述和参数文本中的指令——例如“忽略之前的指令”、隐蔽性指示、人格劫持等。扫描器会遍历整棵模式树,包括嵌套在 oneOf/anyOf 分支内部的属性,因此即便负载被埋藏在四层之下,依然会被揪出来。
与知名工具名称可疑地相似的工具名——包括仅在大小写上做手脚的伪装,例如用 READ_FILE 冒充 read_file,一个简单粗暴的精确匹配比较会完全漏掉这种情况。
接受任意输入的空对象模式,让隐藏字段趁机混入的 additionalProperties: true,以及嵌套超过 4 层的模式结构——这是隐藏恶意参数的常见位置。
要求获取凭据、令牌,或访问敏感文件与内部网络端点的措辞,而这些要求并不符合该工具所声明的用途——这是为工具获得信任后再重新定义其行为埋下的伏笔。
可解码为可读文本的 Base64 数据块——用于夹带载荷——以及 Unicode 同形字符,例如用西里尔字母的 а 冒充你的 a,借此在视觉审查中蒙混过关、夹带指令。
一个被命名为或描述为“只读”的工具,却接受 command, script 或 sql 这样的参数,这就是声称一种能力、实际提供另一种能力。
这些是最初六项未能覆盖的协议特有风险。在全部十一项检测中,该扫描器覆盖了 OWASP MCP Top 10 v0.1-beta(2025)十项风险中的 9 项。第十项——MCP08,即审计与遥测缺失(Lack of Audit and Telemetry)——是静态工具定义无法体现的;这是运行时日志记录的缺口,而不是模式层面的缺口。
硬编码绑定到特定模型的工具——例如声称“只能在 GPT-4 上运行”,或要求与特定系统提示词耦合。这会造成路由依赖,并形成针对该模型的特定攻击面。
声称能够改写对话历史、注入虚假对话轮次,或冒充用户或助手的工具——这类能力可以同时瓦解安全过滤器和审计记录。
非标准的顶层键、供应商扩展模式字段(x-),以及嵌入在描述文本中的长段 base64 数据块——这些都是只查找普通文字的审查者不会留意到的地方。
声称可以访问全局、共享或跨会话状态的措辞,或者默认使用通配符的 session_id 参数——这正是导致租户隔离被打破的典型模式。
一个形如请求头名称的参数——包括 authorization, cookie 或 host 等——又或是通过 MCP 规范的 x-mcp-header 扩展被接入某个出站请求。两者都可能覆盖掉调用方永远看不到的信任边界请求头。
同样的 11 项检测,同样的报告格式,三种运行方式:
POST /v1/suite/guard/scan-mcp 将工具定义放在请求体中。返回一个判定结果(pass / warn / fail),一个 0-1 的风险分数,以及一个发现项数组——每个发现项都包含工具名称、触发的检测项、严重程度、证据和建议。scanMcpTools() 是 Node SDK 中的方法,scan_mcp_tools() 是 Python SDK 中的方法——两者都用带类型的请求/响应结构封装了同一个端点。scan_mcp_tools 工具,在真正调用之前先扫描另一台服务器的工具——无需另外准备 HTTP 客户端。严重程度为“严重”或“高”的发现项会作为 Guard 扫描结果保存在你的租户下,因此一次扫描结果不是一次性的控制台输出——而是一条你可以随时间推移进行审查、排定优先级并最终关闭的记录。
今天扫描结果干净的工具定义,明天可能就会交付截然不同的东西——rug pull 的定义性特征恰恰在于,你审计过的版本并不是你下周实际运行的版本。请在 MCP 服务器每次版本更新时执行扫描,或者按计划定期扫描,而不仅仅是在首次连接时。扫描器只是故事的前半部分,也就是部署前的那一半;而运行时的那一半——在服务器已经通过扫描之后,过滤实际发生的每一次实时工具调用——是 Guard Proxy。两者互不替代:扫描器捕捉的是工具声称会做什么,Guard Proxy 捕捉的是它实际做了什么。
工具投毒是最值得深入理解的一项检测——因为它是唯一一种攻击完全发生在模型推理内部、在网络层没有任何东西可以被拦截的检测。攻击的具体机制、真实世界中的攻击成功率,以及扫描器如何检测它,都在专门文章《MCP 工具投毒:攻击是如何运作的,又该如何检测》中有详细拆解。
调用它的 tools/list 方法获取工具定义,然后把这个数组发送给 VeriSwarm 的扫描器——可以是 POST /v1/suite/guard/scan-mcp、Node SDK 的 scanMcpTools()、Python SDK 的 scan_mcp_tools(),或托管 MCP 服务器上的 scan_mcp_tools 工具。这四种方式调用的都是同一套 11 项检测引擎,返回的也是同一份结构化报告:一个判定结果(pass/warn/fail)、一个 0-1 的风险分数,以及每个发现项对应的严重程度、证据和建议。
十一项确定性检测:工具投毒、域名仿冒(typosquatting)、模式篡改、rug-pull 模式、提示词注入以及过度权限,覆盖了最初的六个风险类别;模型误绑定、上下文伪造、隐蔽通道、不安全的内存引用和请求头注入,则让扫描器覆盖了 OWASP MCP Top 10 v0.1-beta(2025)十项风险中的 9 项——唯一的例外是 MCP08(审计与遥测缺失,Lack of Audit and Telemetry),它不是静态工具定义能够展示的东西,需要的是运行时日志,而不是模式扫描。每一项检测都基于模式与结构——过程中没有任何 LLM 参与,因此同一份工具定义每次扫描都会得到相同的结果。
不会。它是一个静态分析器——依靠正则表达式模式、模式树遍历和 Unicode 规范化,而不是模型调用。这是一个刻意的取舍:概率性判定器之所以有问题,正是因为至少有一次针对某个基于 YARA 的 MCP 扫描器的独立审计,报告了大约 78% 的误报率。确定性检测牺牲了一些召回率,换来的是 CI 流水线真正可以用作质量门禁的结果——同样的输入两次都会得到同样的判定。
两者都可以。在 CI 中,把服务器的 tools/list 响应保存到文件里,作为流水线的一个步骤来扫描——严重的发现项意味着构建失败,而不是事后才发现的 Slack 讨论串。在生产环境中,按计划或在 MCP 服务器每次版本更新时调用该 API 端点,因为一个工具即便曾经扫描干净,也只代表在那一刻是安全的。重新扫描正是发现 rug-pull 的方式——一台在审查期间表现良好、之后才变得恶意的服务器,只有这样才能被抓个正着,而不是被放过。
扫描器负责部署前的那一半:它在你的智能体真正调用服务器之前,先读取声明的工具定义。Guard Proxy 负责运行时的那一半:它位于你的智能体与其工具之间,实时过滤每一次发生的调用。两者互不替代。扫描器捕捉的是工具声称自己会做什么;Guard Proxy 捕捉的是它在调用那一刻实际做了什么。
这是经过实测的,而不是理论上的。MCPTox 基准测试针对 45 个真实 MCP 服务器和 353 个真实工具测试了工具投毒,发现攻击成功率超过 60%,峰值达到 72%——能力更强的模型反而更频繁地配合攻击,因为更擅长遵循指令,也就意味着更擅长服从一条恶意指令。关于攻击机制的完整拆解,以及扫描器的 tool_poisoning 检测项是如何识别它的,都在专门的解析文章中有详细说明。
把一份 tools/list 响应发给 Guard,看看你的智能体一直在读取些什么。Gate 的免费套餐会先为你提供信任评分与事件管道;Guard 的扫描器就构建在它之上。