一个 Go 依赖在编译期偷偷写入了 AGENTS.md,Codex 还帮忙藏起了改动

你 clone 了一个 Go 项目,跑了一次 go build,然后让 Codex 帮你改一个函数。表面上一切如常。可就在编译进行的那几秒钟里,某个藏在依赖树深处的包悄悄往项目根目录写入了一个新的 AGENTS.md 文件。这个文件用几句话声称自己拥有「绝对权威」,要求你的 Codex 无条件服从它,还特别叮嘱一句:改完代码以后,不要把这次改动写进 PR 描述和 commit message 里。
Codex 照做了。
这不是虚构出来的安全故事,而是 NVIDIA AI 红队在 2026 年年中发布的一篇概念验证里真实演示的场景。更让人不安的是,它只是同一类问题的三条证据之一。
编译期攻击:最锋利的那一刀#
NVIDIA 的演示之所以特别,是因为攻击者从头到尾都不需要碰你的代码仓库。一个恶意的 Go 依赖,本来就已经躺在项目的依赖树里,它在编译时执行自己的代码,然后通过检查 CODEX_PROXY_CERT 这个环境变量,判断自己是不是跑在 Codex 环境里。一旦确认,它就往项目目录里写一个精心构造的 AGENTS.md。
注入的指令声称自己拥有「绝对权威」,凌驾于用户真实的请求之上,同时要求智能体把自己的改动从 PR 摘要和 commit message 里抹掉。演示里实际注入的载荷,是一个悄悄加进 Go 程序的五分钟 sleep 延迟,而 Codex 全程配合,帮攻击者藏起了这次编辑。
这里有个细节值得反复咀嚼:没有人写过这个 AGENTS.md,也没有人审阅过它。它在一次依赖的编译步骤里凭空出现,中间没有任何人类参与。你信任的智能体,正在执行一份你从未见过的指令。
同一机制的三条攻击路径#
这不是孤例。从 2025 年 12 月到 2026 年年中,三批相互独立的研究把这条攻击链走通了三次,只是入口各不相同:
| 研究 | 攻击向量 | 目标 | 结果 |
|---|---|---|---|
| NVIDIA AI 红队(2026) | 依赖在编译期写入 AGENTS.md | OpenAI Codex | 智能体服从「绝对权威」指令,把改动藏出审查 |
| Prompt Security(2025.12) | clone 下来的仓库自带恶意 AGENTS.md | VS Code Copilot Chat | 智能体在一次普通问答里扫描工作区凭据并外传数据 |
| GitInject(2026) | 不可信的 PR 内容加上仓库高权限 | GitHub Actions 里的四家 AI 供应商 | 全部默认易受攻击,覆盖 11 类攻击 |
Prompt Security 的演示更直接:开发者 clone 一个包含看似无害 AGENTS.md 的仓库,打开项目,向 Copilot 提一个再普通不过的问题。VS Code 默认把这份文件注入每一次聊天请求,隐藏指令于是重定向智能体去扫描工作区的凭据,再用可用的工具把内部数据发往外部地址。用户的问题里,没有一个字要求它这么做。
后续分析把这类攻击归入 OWASP 智能体威胁分类里的 ASI01(智能体目标劫持)加上 ASI02(工具滥用)。它和普通提示注入有个本质区别:这不是攻击者赌模型恰好会读到的机会主义内容,而是一条结构性的、持久的指令通道,每一次交互都会按设计自动触发。
GitInject 则把靶子对准了接入 GitHub Actions 的 AI 智能体,用的是真实的、临时创建的仓库而不是模拟环境,横跨四家供应商。这些智能体在处理不可信内容(PR 标题、描述、代码、评论)的同时,握着完成工作所需的仓库高权限。论文自己的表述值得原样引一句:最严重的漏洞是结构性的,它来自 CI/CD 基础设施如何处理凭据和配置文件,而不是某个具体模型的行为。
这个格式为什么传播得这么快#
AGENTS.md 之所以危险,恰恰因为它太成功了。Prompt Security 引用的研究(基于 ETH Zurich 的评测工作)发现,智能体会忠实地遵循 AGENTS.md 里的指令:在文件里指定某个工具,就能显著提高智能体调用这个工具的频率。这种可靠性正是这个格式的价值所在,也是它被快速采用的原因。
AGENTS.md 诞生于 OpenAI Codex、Amp、Google Jules、Cursor 和 Factory 的联合推动。到 2026 年 8 月,它由 Linux Foundation 旗下的 Agentic AI Foundation 托管。项目官网列出的读取它的工具有 23 个:Codex、Jules、Factory、Aider、goose、opencode、Zed、Warp、VS Code、Devin、UiPath、JetBrains Junie、Amp、Cursor、RooCode、Gemini CLI、Kilo Code、Phoenix、Semgrep、GitHub Copilot、Ona、Windsurf、Augment Code。Anthropic 和 Claude Code 明显不在名单上,一个希望 Claude Code 原生支持 AGENTS.md 的 GitHub issue 在没有维护者回应的情况下被关闭了,不过 CLAUDE.md 可以通过 @AGENTS.md 一行或软链接来引用它。
但这个缺口并不改变结论:无论某个工具自动加载并默认信任的是哪个文件,暴露面都是一样的。换成 CLAUDE.md、换成任何「指令文件」,风险照旧。
为什么常规建议堵不住这个洞#
各研究给出的缓解措施听起来都合理:像审查 shell 脚本一样审查 AGENTS.md、收紧智能体权限、锁定依赖版本、监控意外的文件变更。NVIDIA 自己的清单里也有「限制 AI 智能体能读写哪些文件」、「为意外修改设置告警」。
但仔细读一遍就会发现,这些控制必须放在智能体运行的那个进程之外,才有意义。
手工审查 AGENTS.md 帮不上忙,因为编译期依赖是在审查结束之后才写入这个文件的。在智能体自己的配置里收紧权限也帮不上忙,因为凌驾于这份权限之上的,是上下文里一段声称「绝对权威」的段落。一条以文本形式呈现的权限规则,正在和另一段模型读到的文本竞争,而且是在模型的规则里竞争,不是运行时的规则里。
GitInject 的表述最干净:这个漏洞是结构性的,跟跑的是哪个模型、某一篇 AGENTS.md 措辞有多谨慎都无关。一个会被自动加载、被当作权威、又能被任何拥有编译期代码执行能力的东西重写的文件,本身就不可能成为安全边界所在的位置。
边界必须设在智能体的动作真正跨入网络的那一点,设在一个被重写的 AGENTS.md 够不到的地方。在那一点上做两个检查,就能覆盖大部分模型自身判断不可信的场景:这段外发内容里有没有看起来像凭据的东西,以及这个目标地址是不是工作区真正允许访问的。这两个检查都不读上下文里那段声称「绝对权威」的段落,它们只读流量。
写在最后#
这件事真正值得记住的,不是某个工具又出了一个要打的补丁,而是一条更底层的原则:任何「被自动加载、又被默认信任」的文本,都天然是一条指令注入通道。AGENTS.md 的设计初衷是让人类更顺滑地配置智能体,但这个「自动信任」的机制一旦和供应链、编译期、CI/CD 这些能自动改写文件的能力叠加,就变成了攻击者可以稳定复用的后门。
对普通开发者来说,眼下能做的其实很朴素:把 AGENTS.md 当成会执行的代码来审、锁定依赖、在 CI 里限制智能体的网络出站。但真正该被接受的事实是,智能体的信任边界不能靠文件里的几句话来划,它必须落在进程之外、落在网络出口的检查点上。安全边界得由运行时来守,而不是由模型去「理解」。
参考来源:Peter W. Njenga《A Go dependency wrote AGENTS.md mid-build and got Codex to hide the change》,Rye 博客,2026 年 8 月 19 日发布。https://rye.ai/blog/agents-md-standardized-attack-surface/