证据 · 自评 · 有边界 · 可重跑

MCP 安全边界:我们实际检查了什么。

这个页面的存在,是因为仓库里的安全证据此前只以 GitHub 文件目录的形式存在,搜索结果无法落在上面。 下面的每个数字都由本仓库的某个命令产出,而每一节最先说明的,是那个方法的止步之处。 这里没有任何内容构成生产就绪认证,也没有任何内容声称绝对安全。

本页开头的说法是可核对的:23 次攻击探测由 tools/security-attack-regression.mjs 数出来,15 个工具名由 packages/mcp-server/src/server.js 数出来。tools/public-repo-check.mjs 会拿这两个派生值来校验本页,所以如果新增了攻击用例或工具而没有同步本页,构建会直接变红, 而不是让这段文字悄悄失真。假如这句话与代码不一致,以代码为准。

免凭据证据:一次运行如何证明没有调用 provider(英文) · 安全证据目录 · 已发布 MCP 镜像实际暴露什么(英文)

攻击回归:23 次探测,全部拦住

tools/security-attack-regression.mjs 会启动一个真实的网关进程,并向它发起 23 次攻击 用例:跨租户隔离、请求头伪造、越权创建与过滤、viewer 角色越界访问对话与管理接口、预算耗尽与限速 (都返回 429)、跨租户密钥吊销、已吊销密钥即时失效、疑似机密文本不入缓存、匿名与低权限访问 /mcp/tools、未知上游被拒绝、超大的 MCP 参数被拒绝,以及 /metrics 需要 鉴权且不包含任何机密。每个用例打印 DEFENDED 或 BREACH,任何一次突破都会 让进程以非零退出。

node tools/security-attack-regression.mjs

已提交的 安全演练证据页(英文)是执行上面的脚本并解析其 输出生成的。只有在恰好解析出 23 条判定、且没有任何一条是突破时,它才允许落盘;而页面上的数字取自 解析结果,不是模板里手写的常量。换句话说,新增第 24 个用例却忘了改别的东西时,生成器会拒绝写出, 而不是继续发布一个失真的计数。

这个方法的止步之处。这是一套由写代码的人自己编写的回归。它不是第三方渗透测试, 也不是审计。它跑的是源码构建,所以一次绿色运行并不能认证已经推到 registry 的那个容器镜像—— 那是下面单独处理的问题。

两次已发布镜像审查,用了两种不同方法

它们不是同一种检查,覆盖的也不是同一片范围。把两者读成同一个数字,正是这一节要避免的错误。

按产出方法区分的在册审查
镜像方法需要什么结论
0.8.0 直接从 registry 读取分层 tarball 不需要 Docker 引擎;不执行任何东西 非 root 的 node 用户,8 个 setuid 文件与 3 个 setgid 文件;而 linux/arm64 标签里的 8 个原生模块有 4 个是 x86-64,因此在 arm64 主机上加载它们的 那条路径会失败
0.4.9 用 Docker 导出容器文件系统 一个可用的 Docker 引擎 默认 root 用户,11 个来自基础镜像的 SUID/SGID 文件;arm64 模块确实是 AArch64。 agent skill 里按摘要固定的那一份,依据的正是这次审查

不用 Docker 也可以自己重读:

node tools/inspect-image-filesystem.mjs 0.8.0
node tools/verify-image-roster.mjs 0.8.0

第二条命令回答的是另一个问题——已发布镜像实际暴露了哪些工具名。它从镜像字节里读出 0.8.0 是 15 个、0.4.9 是 9 个,依据不是任何文档。正因如此,安装说明里 那个被固定的摘要才重要:那 15 个名字里有 6 个在这个较旧的镜像里并不存在。arm64 那条发现展开在 《容器里装着另一种架构的原生模块》。

为什么最新的一次审查并不是定心丸。0.8.0 的审查正是发现了 架构错配的那一次。这里出现更新的文档,意味着检查得更多,而不是问题更少。

0.5.0、0.6.0 和 0.7.0 没有内容审查在册。0.4.8、 0.4.0 和 0.3.2 有,链接见 安全索引。

这个页面不能证明什么

如果你发现了问题

请通过安全政策私下报告, 不要开公开 issue。如果你重跑上面的命令后得到的结果与本页不一致,那本身就值得报告:这里的数字都是 派生的,所以对不上就说明要么产物变了、要么推导变了,我们宁愿早知道,也不守着一个失真的说法。