2026年10月18日 1 分钟阅读

MCP 工具升级后行为变了,Agent 却毫无察觉?用 RugSnare 检查契约漂移

tinyash 0 条评论

MCP 服务器升级后,工具名称可能没变,描述和参数 Schema 却已经不同。对人类来说只是一次依赖更新;对 Agent 来说,描述是它判断何时、如何调用工具的指令。若描述被悄悄改写,或者参数约束被放宽,原先审查通过的集成就可能呈现新的行为边界。

RugSnare 针对的是这个“批准之后”的缺口:它把 MCP 工具的名称、描述和 inputSchema 规范化后计算哈希,保存为基线,再在升级时比较当前契约。它不是代码供应链扫描器,也不能证明服务器实现安全;它提供的是可审查、可自动化的契约变更检测。

先建立基线,再把差异放进 CI

项目 README 给出的基本流程是初始化、扫描、比较。示例使用 .mcp.json;请按自己的 MCP 客户端配置实际路径调整:

npx rugsnare init
npx rugsnare scan --config .mcp.json
npx rugsnare diff --config .mcp.json

scan 为当前工具契约建立固定基线,diff 则重新读取服务器暴露的工具并与基线对比。README 指出检测到漂移、新增或移除项时,diff 会以退出码 1 结束,因此可以直接作为 CI 门禁:

- name: Check MCP contracts
  run: npx rugsnare diff --config .mcp.json

基线文件应纳入代码审查和版本控制。否则,若基线本身被随意更新,比较结果就失去意义。建议升级 MCP 服务器时先在单独分支运行检查,阅读差异并确认变更意图,再由维护者更新基线;不要把“重新扫描并提交”做成无人审查的自动步骤。

差异不等于恶意:要看变化方向

RugSnare 将变化按性质分类,而不是把每个哈希变化都简单说成攻击。约束收紧、类型变窄或参数变为必填可能影响兼容性;约束移除、类型放宽或新增可选参数则会扩大接受范围;纯序列化格式变化或描述文字调整也需要与真正的 Schema 语义变化区分。工具名新增、移除同样值得检查,因为 Agent 工作流可能仍在调用旧名称。

实际处理时,重点问三件事:这项变更是否由上游发布说明解释?Agent 的可调用范围是否扩大?调用方是否需要同步修改?对纯格式差异可确认规范化是否消除了无意义噪声;对描述变化要读新旧文本;对 Schema 变化要比较必填字段、类型、枚举和边界。CI 的红灯是审查信号,不应被当作自动回滚或恶意判决。

需要会话内监控时再启用代理

项目还提供可选的实时代理模式,可在 MCP 服务进程与客户端之间观察会话中的契约变化。README 示例:

rugsnare run --name files --mode enforce -- \
  npx -y @modelcontextprotocol/server-filesystem /tmp

enforce 模式会隔离新出现或发生漂移的工具;代理默认 fail-open,即自身逻辑出错时优先转发消息。严格环境可配置 failMode: "closed" 或使用 --fail-closed,但这会把代理故障转化为调用失败。生产部署前应在测试环境验证启动参数、客户端兼容性和故障策略,尤其不要未经评估就把示例中的 /tmp 路径照搬到真实文件服务器。

明确它的边界

契约固定能发现“Agent 看到的工具定义发生变化”,却无法发现实现代码在契约不变时被植入后门,也不能替代包签名验证、依赖审计、沙箱和最小权限。RugSnare README 本身也将实现层代码恶意行为列为范围之外。更稳妥的做法是分层防护:审查并固定契约、验证软件来源、限制服务器权限,并在调用侧控制敏感操作。

该项目仓库声明 Apache-2.0,README 标示 Node.js 18 及以上,并称 CLI 无 npm 运行时依赖。安装前仍应核对所用发行版本及官方说明。对于已经纳入团队工作流的 MCP 服务,先在 CI 加入只读差异检查,再逐步评估会话代理,比一开始就启用强制拦截更容易控制风险。

相关链接

发表评论

你的邮箱地址不会被公开,带 * 的为必填项。