一个 AGENTS.md 就让 AI 编程助手装木马:Codex 成功率超 90%

一个放在下载目录里的纯文本文件,就能把 AI 编程助手变成安装恶意软件的执行者。安全公司 Forever Security 披露,某客户机器的 ~/Downloads 目录中存在一个伪装成工程笔记的 AGENTS.md,它试图让 AI 编程助手安装与 MALFEX npm 供应链活动关联的 function-color 包。客户的安全控制拦下了这次安装,但随后的复现实验显示,OpenAI Codex 在超过 90% 的测试运行中照着这份文件做了。

事件经过

AGENTS.md 是 AI 编程助手生态里被广泛使用的约定文件名,用来告诉助手项目结构、开发规范、允许执行的命令。助手在某个目录启动时,会把这个目录里的指令文件当作项目上下文读进来——这是设计功能,不是缺陷。

被发现的这份文件把这个功能当成了投递通道:内容看起来是寻常的技术笔记,实际指令是安装 function-color。研究方无法确认文件最初是怎么进入下载目录的,但他们验证了最省事的那条路径——浏览器可以在用户既不点击、也不授权的情况下把文件写进下载目录,而下载目录恰恰是对可执行文件限制较严、对纯文本毫无限制的地方。

恶意包链条:静默、跨项目、不留痕

function-color 本身是空壳,它唯一的动作是把 function-flag 作为依赖拉进来。function-flag 的 postinstall 脚本从远端下载一个 Windows 可执行文件,存成 %APPDATA% 下的 node.exe,然后在后台启动。

function-color  (wrapper,无自身载荷)
  └─ function-flag  (dependency)
       └─ postinstall: 下载 → %APPDATA%
ode.exe → 后台执行
          下载逻辑位于空的 catch 块内:失败无报错、安装日志无痕迹

到 10 月初,这两个包在 npm 上仍可正常安装,也没有任何安全公告标记它们。空的 catch 块是个细节,但很关键:它让安装失败与安装成功在日志上看起来完全一样,排查时容易误判为”没中”。

两个助手,两种打法

Codex 的指令更直接:在 ~/.codex/config.toml 里注册一个新的 server 条目,并安装恶意包。config.toml 是机器级配置,对每个会话生效,所以一旦写入,影响范围不止下载目录里启动的那一次会话,而是这台机器之后的所有项目。文件里还要求助手在安装过程中绕过审批与沙箱控制。测试在隔离虚拟机中执行,多数轮次用无害替代包,真实包只在受控环境里跑过。

Claude Code 需要另一种写法。植入的 CLAUDE.md 模仿内部网关配置文档,目标是往项目的 .claude/settings.json 里写一个自定义 API 端点。如果端点由攻击者控制,助手发出的每一次 API 调用连同会话令牌都会经过攻击者的服务器,令牌拿到手就等于接管账号。Claude Code 通常会就这类写入弹审批,对明显可疑的请求也经常拒绝,但”工程文档”式的包装让写入要求在大约一半的测试中获得了批准。

没有补丁可以打

Forever 的结论很干脆:OpenAI 和 Anthropic 都没有可修的东西。助手读工作目录里的指令文件、按文件内容执行,这正是它们被造出来要干的事。研究方拿浏览器渲染钓鱼页面作类比——浏览器没坏,坏的是那个页面。责任因此落到使用者和组织一侧。

数据也支持这个判断:Forever 自己的遥测显示,约一半客户会在下载目录里启动编程助手,约四分之一的助手会话同时开着真实浏览器,而很多情况下文件落进目录时并没有人盯着会话。

该怎么做

  • 不要在下载目录启动编程助手。直接从项目目录启动,把 ~/Downloads 当成敌对环境处理,而不是工作目录的默认值。
  • 读一遍不是自己写的指令文件。AGENTS.md、CLAUDE.md、以及各种 .cursorrules 类的配置,包括刚 clone 下来的仓库里带的那些。
  • 查配置有没有被动过:~/.codex/config.toml 里出现不认识的 server 块、.claude/settings.json 里出现不是你设置的 API 端点,都属于确认被投毒的迹象。
  • Windows 侧看 %APPDATA%\node.exe。正常 Node 安装不会把解释器放进 Roaming 目录,这个文件出现基本可以判定 function-flag 已经跑过。
  • 确认后按凭据泄露处理。该会话的登录令牌要立刻轮换,光删掉那个 md 文件没有意义。
  • 保留审批和沙箱。审批提示不是可靠屏障——Claude Code 的实验已经证明了这点——但把成功率从”一半”压到”更少”,本身就是收益。

这类攻击的特别之处在于它绕开了传统漏洞管理:没有 CVE、没有版本号、没有补丁窗口,扫描器也扫不出来。能做的只有收窄 agent 的工作目录、审阅指令来源、以及在权限层面假设它随时可能被说服。

参考来源