你还没打字,仓库里的代码已经跑了:GitSpawn 漏洞与 Hermes 的修复

周五下午,同事把一个项目打成 zip 发给你:“帮我看看这个 bug。“你解压、把文件夹拖进 Hermes、准备敲第一句指令——但就在你打字的这几秒里,一段不属于你的代码已经以你的身份在电脑上悄悄执行完了。没有弹窗、没有审批、屏幕上什么都没有。这不是科幻片,是 2026 年 9 月被安全公司 Manifold Security 正式披露的一类真实漏洞,代号 GitSpawn,波及 Claude Code、Codex、Cursor、Goose、Qwen Code、Grok Build 和 Hermes Agent 等几乎所有主流 AI 编程工具。好消息是:Hermes 已经在 9 月 2 日合入修复(PR #101483,当前在 main 分支)。
漏洞原理:你打开的仓库,替你“跑”了一条命令
AI 编程工具(包括 Hermes)在启动时,会先自动跑几条 git 命令来了解当前项目:当前在哪个分支、改了哪些文件。这是它自己发起的、发生在任何提示词、任何工具调用、任何信任确认之前的上下文收集——毕竟它得先知道自己在哪,才能开始干活。
问题出在 git 的一个性能优化功能上:core.fsmonitor。大仓库里,git 不想逐个扫描文件来判断“哪些变了”,于是允许你配置一个辅助程序替它回答。git 在每次刷新索引(index refresh)时都会运行这个程序——而 git status、git diff 这类命令都会触发索引刷新。
关键点在于:这个配置是从仓库自己的 .git/config 里读的。也就是说,一个恶意仓库可以自带这样一段配置:
[core]
fsmonitor = /tmp/pwn.sh
然后你只要打开这个仓库(哪怕一句话都没说),Hermes 自动跑的 git status 就会让 git 执行 /tmp/pwn.sh——以你的用户权限、在你的机器上、绕过沙箱、没有任何审批界面。攻击者拿到的不只是“能跑代码”,而是你的 SSH 密钥、云凭证、shell 里的 token 和整台机器的立足点。
core.fsmonitor 只是其中一种执行点。Manifold 的报告中还提到了 core.hooksPath(checkout 时跑钩子)、pager/editor/credential 设置,以及更隐蔽的 .gitattributes 属性驱动([diff "x"] command= / textconv=,渲染 diff 时执行)。后一类尤其麻烦:驱动名是攻击者自己起的,用环境变量枚举不到,只能靠命令行旗标封堵。
传播方式:为什么 git clone 是安全的,zip 不是
这条漏洞有个反直觉的特点:从网上 git clone 一个恶意仓库是安全的。git 的 clone/fetch/pull 根本不会传输 .git/config——那是你本地仓库的私密文件,远端长什么样跟你无关。
危险的是以“目录文件”形式到达的仓库:.git 目录原封不动躺在里面。共享的 zip、网盘同步文件夹、U 盘、同事直接拷贝的项目目录——这些途径都会完整保留对方仓库的 .git/config。Manifold 团队做验证时用的就是一个 zip。
所以判断标准很简单:凡是“别人打包好传给你的项目文件夹”,在交给 AI 工具打开之前都要多留个心眼;凡是 clone 下来的,天然安全。
业界反应:八个产品,披露时四个还没修
Manifold Security 在 9 月 1 日发布完整报告,披露了横跨 7 个 AI 编程工具的 8 项发现。截至报告发布时的状态:
| 工具 | 状态 |
|---|---|
| Claude Code(fsmonitor 路径) | 已修复(2.1.196) |
| Claude Code(ultrareview 路径) | 披露时未修复(2.1.252 复测仍中招) |
| Goose | 已修复(1.44.0,CVE-2026-72718) |
| Codex / Cursor | 已修复 |
| Hermes Agent | 披露时未修复,9 月 2 日已合入修复 |
| Qwen Code / Grok Build | 披露时未修复 |
The Hacker News 在 9 月 2 日的报道里还把 Hermes 列为 “fix pending”——但实际上 Nous Research 当天就把修复合并进了 main,比报道里的状态又新了一天。
Hermes 的修复:把“裸奔的 git”变成“消毒的 git”
Hermes 的修复(PR #101483,commit f6234d00c5)思路很直接:凡是 Hermes 自己发起的 git 探测,一律在一个消毒过的环境里运行,仓库自带的配置一概不认。
具体两层防护:
第一层——环境消毒(noninteractive_git_env()):所有自动探测现在默认用一套“非交互 git 环境”,通过 GIT_CONFIG_* 机制把 core.fsmonitor、core.hooksPath、pager、editor、credential helper 全部钉死为无害值,同时忽略全局和系统配置。git status 刷新索引时,再也没有“仓库指定的辅助程序”可以跑。受保护的调用点包括上下文收集(coding_context)、网关的项目树构建、@diff/@staged 引用、goal 门禁指纹和 -w 启动时的 worktree 添加。
第二层——命令行旗标(harden_git_argv()):环境变量封不住 .gitattributes 属性驱动(驱动名是攻击者起的,枚举不到),所以对 diff/show/log/blame 这类渲染 diff 的子命令,自动插入 --no-ext-diff --no-textconv,从命令行层面掐断 [diff "x"] command= 和 textconv= 两个执行点。
配套的还有一套真实 git 的端到端回归测试:故意制造一个带恶意配置的仓库,逐个断言每一条自动路径都不会执行 fsmonitor、hooks、external-diff 或 textconv。
你现在该做什么
- 确认自己的版本:修复合入于 9 月 2 日,当前还没进任何正式 release(最新版 v0.21.0 发布于 8 月 31 日,早于修复)。如果你追求第一时间安全,可以从 main 分支更新或等下一个补丁版本;在升级之前,把下面的习惯先养成。
- 警惕“文件形式”的仓库:对 zip、网盘同步文件夹、U 盘里拷贝来的项目目录,先检查再打开。
git clone的仓库则无需担心。 - 收到可疑项目时自查:在交给 Hermes 之前,看一眼仓库的
.git/config和.gitattributes:
cd path/to/suspicious-project
git config --get core.fsmonitor # 有输出就要警惕
git config --get core.hooksPath
grep -nE "command *=|textconv *=" .git/config
- 别在可疑目录里直接开会话:如果必须看代码,先
git clone一份干净的再让 Hermes 打开。
这次事件和之前我们写过的 SSH config 审批门禁 是同一类教训:AI 工具自动执行的底层命令,必须假设输入是不可信的。Hermes 这次的修复把“上下文收集”这个最早期、最无感的环节也纳入了信任边界——在你看不见的地方,它也默认仓库可能是敌人。