- 类别
- AI 与 MCP
- 平台
- 命令行 · macOS / Linux / Windows
- 许可
- MIT
面向 Model Context Protocol(MCP)服务的安全网关和扫描器。它夹在 MCP 客户端和服务端之间检查 JSON-RPC 流量,命中严重规则就拦下这条消息。完全离线:不调用 LLM,没有遥测。
在浏览器里试试
下面的检测规则是把 Go 版规则移植成 JavaScript,在你的浏览器本地运行,粘贴进来的内容不会离开这个页面。样例数据都是虚构的,里面的凭据是官方文档示例或一看就是假的。
粘贴或修改一条 MCP 消息,规则会随输入实时运行。先选一个场景试试。
先把你批准过的工具集固定下来(pin),再让服务端偷偷改掉其中一个工具。重新扫描时会逐个比对每个工具的 SHA-256。
把一段简短会话放进 warden proxy 回放。每条消息经过网关时都会被检查,命中严重规则就在网关处拦下。
为什么要在运行时检查
MCP 的常见攻击手法已经很清楚:工具投毒(在工具元数据里藏指令)、rug pull(已批准的工具悄悄改了定义)、 通过工具返回结果做提示注入,以及凭据外泄。现有的开源扫描器在安装时检查配置和元数据,看不到调用时真正流过的内容; 网关类产品主要管路由、鉴权和治理。mcp-warden 补的是运行时这一块:双向检查实时流量,能在消息到达模型或服务端之前把它拦下。
检查什么
| 类别 | 检查位置 | 规则 | 级别 |
|---|---|---|---|
| 工具投毒 | tools/list 响应 | 工具的名称、描述或输入 schema 里出现指令式语句(9 条模式),或零宽 / Unicode tag 字符 | critical |
| Rug pull | tools/list 响应 | 工具的 SHA-256 与 warden.lock.json 对不上;从未固定过的新工具单独报出 | critical / warning |
| 提示注入 | tools/call 结果 | 返回文本里出现同样的指令式语句;结果里出现隐形字符 | critical / warning |
| 数据外泄 | tools/call 参数和结果,以及其他响应体 | AWS access key ID,GitHub、Slack、OpenAI、Google 的 key,私钥块,JWT | critical |
代理怎么判定
- 开启
blockOnCritical时,任何严重级发现都会让这条消息被替换成 JSON-RPC 错误(-32001,"blocked by mcp-warden security policy")。如果问题出在请求上,服务端根本收不到这次调用。 - 警告级的照常转发,并写入 JSONL 审计日志。
warden scan遇到严重级发现会以非零码退出,可以直接卡在 CI 里。
warden pin https://my-mcp-server.example.com/mcp --out warden.lock.json
warden scan https://my-mcp-server.example.com/mcp --lock warden.lock.json
warden proxy --config warden.json # 让客户端改连代理地址 离线、零依赖
只用 Go 标准库,go.mod 里没有任何第三方模块。检测器都是纯函数,同样的输入永远得到同样的结果,
被检查的流量不会离开进程。工具哈希是对名称、描述和输入 schema 按键排序后的 JSON 做 SHA-256,
所以只调换 schema 里键的顺序不会误报 rug pull。
当前状态
早期开发阶段(v0.1.0),接口和规则还会变。代理目前只支持 Streamable HTTP(还不支持 stdio),SSE 响应体按纯文本粗扫; 基于模式匹配,能抓已知的写法,抓不住新的混淆手法。把它当作多层防御中的一层,而不是保证。
关于这个演示
语句模式、正则、隐形字符范围、严重级别和哈希算法都照 Go 源码移植。移植版和 Go 版检测器在同一组测试样例 (包括仓库自带的测试用例)上对比跑过,发现结果和工具哈希完全一致。只有两处是这个页面独有的:rug pull 页签里的差异对比 (真实的 lockfile 只存哈希),以及精简过的审计日志。