装个 MCP 差点被写入 HERMES_YOLO_MODE:官方堵上了目录安装的环境变量漏洞


想象一个场景:你在 Hermes 的官方 MCP 目录里看中了一个 server,点击安装,它弹出一堆环境变量让你填——你填了 API key,装完一切正常。但假如这个目录条目本身是恶意的,或者只是写得不规范呢?在 8 月 26 日修复之前,安装请求里带的任意环境变量都会被原样写进你 profile 的 .env 文件——包括 HERMES_YOLO_MODE 这种直接改变你安全策略的开关。换句话说,装一个 MCP 工具,理论上等于把“以后每次启动自动进入 yolo 模式”的钥匙交了出去。这个洞现在被堵上了(PR #91139)。

漏洞到底长什么样

问题出在 POST /api/mcp/catalog/install 这个接口。修复前它接受一个任意的 env 映射,然后把每个非空值都持久化到所选 profile 的 .env 文件,之后才执行安装。接口本意是接收用户在安装向导里填的凭据,但既然它来者不拒,一个请求就可以把 HERMES_YOLO_MODE(或者其他任何运行时控制变量)挂在一个看似正常的凭据提交上,写入 .env,下次进程启动就生效。

更微妙的隐患是“通用持久化”本身的权力:一旦某个接口能往 .env 写任意键,它就成了一台通用写入原语——能替换 MCP 目录的信任根、能拿到 Copilot ACP 的可执行文件权限、能注入任何 HERMES_* 控制。MCP 目录本来只是“帮你填凭据”,不该拥有这种能力。

修复:目录凭据是封闭 schema

修复后的行为:

  • closed schema 校验:每个目录条目声明自己需要哪些环境变量(auth.env 列表)。提交里出现任何未声明的名字 → HTTP 400,在第一次写入或安装动作之前就拒绝;
  • 先验证后写入:完整的 env 映射会在写入第一个值之前整体校验,混合了合法和非法键的请求不可能“写一半”;
  • 名字级 denylist:共享的环境变量写入器会拒绝持久化 Hermes 运行时与审批控制变量——HERMES_YOLO_MODEHERMES_ACCEPT_HOOKSHERMES_REDACT_SECRETSHERMES_INTERACTIVEHERMES_EXEC_ASKHERMES_GATEWAY_SESSIONHERMES_CRON_SESSIONHERMES_SESSION_KEYHERMES_CONFIG_PATHHERMES_ENV_PATH 等都在名单上,损坏的目录条目也没法“自我授权”;
  • 报错不泄密:错误信息只列出被拒绝的变量名,绝不回显你提交的值。

注意 denylist 是名字级的,不是一刀切封掉所有 HERMES_*——因为很多集成凭据本身就遵循 HERMES_* 命名约定(比如 HERMES_LANGFUSE_PUBLIC_KEY),把整个前缀封死会打挂现有的 provider 配置向导。堵的是“运行时控制”,放行的是“集成凭据”。

对正常用户有什么影响

几乎没有。桌面端本来就只提交目录条目声明过的凭据字段,所以正常安装流程的请求形状完全不变;手动配置的 MCP server 也完全不受影响。这次修复是纯粹的防御加固:你照常使用,坏人少了一个入口。

给你的建议

  • 正常用目录安装:官方目录的安装流程现在有封闭 schema 兜底,凭据只写声明过的键;
  • 手动配置 MCP 时瞄一眼 .env:如果你自己手写 MCP server 配置、自己往 .env 里放变量,记得遵循最小权限——不要放 HERMES_YOLO_MODE 这类开关,需要时用 hermes config 或专门的 CLI 控制;
  • 给目录贡献条目:如果你在维护自己的 MCP server 目录条目,把需要的环境变量全部写进 auth.env 声明里,用户才会看到正确的表单,安装也不会被 400 拦下。

小结

这次修复的本质是权限收窄:MCP 目录安装从“能写任意环境变量”收窄为“只能写声明过的凭据”,并且对安全控制类变量设置名字级黑名单。安全修复往往是最容易被忽视的更新,但它保护的正是你最容易放松警惕的环节——第三方工具的安装向导。想深入了解 Hermes 的 MCP 生态,可以看看 MCP 配置上下文变量官方远程 MCP 目录 这两篇;如果你是靠 webhook 通知 监控系统状态的,顺手把这个修复一起部署了更安心。