仓库指令文件如何成为编程智能体攻击入口
文章介绍攻击者利用 AGENTS.md、CLAUDE.md 注入指令,诱导编程智能体安装恶意依赖、修改配置或重定向 API 流量的案例。研究测试表明,智能体已有的执行权限可能被看似普通的 Markdown 指令滥用。
AI 深度解读
一份 AGENTS.md 或 CLAUDE.md,既能告诉 AI 编程代理怎么跑测试,也可能诱导它安装恶意依赖、修改全局配置。原文讨论的提示注入(Prompt injection),就是把攻击指令混进代理会读取的内容,再借用它已有的权限执行。
这篇文章最有用的地方,是把风险落到了启动目录、依赖安装、MCP 配置和凭证管理上。不过,研究展示的攻击链、作者提出的防护建议,以及产品默认保护的实际效果,需要分开判断。
一份 Markdown,为什么能影响整台机器
按原文转述,Forever Security 在客户的 Downloads 目录发现了恶意 AGENTS.md,要求 Codex 安装名为 function-color 的 npm 包。这个包是恶意软件,安装在运行前被拦截。CSO Online 于 2026 年 10 月 26 日报道了相关研究。
研究人员随后做了主动测试。原文提到两个结果:恶意 MCP server 被写入 Codex 的机器级配置,后续会话甚至切换项目后仍会加载;捕获的 OAuth token 能在真实 API 上重放,风险因此可能延伸到账户接管。研究还展示了恶意网站触发此类下载、不再额外弹出批准提示的情况,但没有交代完整条件。
这里有个材料缺口:原文在引出主动测试后,直接跳到了结果,没有给出完整步骤、样本量和成功率。不能据此补出攻击细节,也不能把发现恶意文件等同于客户机器已经失陷。
攻击入口也不限于 Downloads。克隆仓库里的 README、.cursor/rules,下载的模板,node_modules 中的包文件,网页、issue、PR 评论,以及工具和 MCP 响应,都可能携带恶意指令。
文件提供的是文字,真正执行操作的是持有你所授权权限的代理。
对前端开发者来说,危险动作可能只是一次看似合理的「先安装依赖」。攻击者不一定需要提供可执行文件,只需要让代理把外部文本当成下一步操作依据。
先审查它读什么,再限制它能做什么
原文建议只在自己创建或审查过的项目目录启动代理,避开 ~/Downloads、~ 和刚解压的目录。理由是:Claude Code 会读取启动目录及上级目录中的 CLAUDE.md;Codex 也会在受信任目录中读取相应的 AGENTS.md。具体加载边界仍取决于产品的信任设置,不能理解成所有目录都会无条件生效。
接手新仓库时,可以先用原文命令查找常见指令文件:
find . -maxdepth 3 \( -name "CLAUDE.md" -o -name "AGENTS.md" -o -name "GEMINI.md" -o -path "*/.cursor/rules/*" \) -not -path "./node_modules/*"
注意 -maxdepth 3 和排除 node_modules 的条件:它适合初筛,覆盖不了更深目录及依赖包中的文件。重点检查安装包、修改环境变量、访问陌生 URL,以及触碰 ~/.claude、~/.codex 或 MCP 设置的要求。
自己的仓库则应把指令文件纳入代码审查。原文给出的 CODEOWNERS 示例,把 CLAUDE.md、AGENTS.md、.claude/、.codex/ 都交给 @your-team/leads。这能明确审查责任,但是否强制批准,还要看仓库规则。
另一层约束是保留审批和沙箱。原文点名 Codex 的 --dangerously-bypass-approvals-and-sandbox,以及 Claude Code 的 --dangerously-skip-permissions,建议不要把它们设成日常启动习惯或别名。频繁遇到批准请求时,优先放行确有必要的单条命令。
作者还在 Claude Code 的项目或用户 settings.json 中配置了以下拒绝规则:
{
"permissions": {
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(~/.ssh/**)",
"Edit(~/.claude/**)",
"Bash(curl:*)"
]
}
}
注意 Bash(curl:*) 只针对这里指定的命令,不能据此认为所有网络外传路径都已封住。这个例子的价值,是把「代理不该做什么」落实成权限规则,而不只写在提示词里。
安装依赖和保存凭证,是另外两道关
真实发现中的第一步就是 npm install,因此原文把依赖治理单独列了出来。
pnpm 的 minimumReleaseAge 可以拒绝安装发布时间未达到指定年龄的版本,给恶意版本暴露和下架留出时间。原文没有给出建议阈值,也没有量化拦截效果;它能拦住过新的版本,不能证明旧版本安全。
另一项是 GitHub package firewall。按原文,GitHub 于 2026 年 10 月 20 日面向 Enterprise Cloud 开启公开预览,用它在代理与 npm registry 之间拦截带恶意软件公告、或仍处于冷却期的包。这个能力有产品范围,不能直接当成所有团队现成可用的配置。
凭证方面,作者建议开发环境使用独立、短期、低权限的密钥,把生产秘密留在部署平台的环境设置中。原文还提到,自 2026 年 10 月 13 日起,启用 secret scanning 的仓库,其 GitHub push protection 默认拦截 Anthropic API keys,也包括免费的公开仓库。
不过,提交时拦截密钥解决的是另一条泄露路径。代理若已经能读取本机凭证,就仍可能在提交发生前暴露它们。
还要检查持久化配置:Claude Code 可以运行 claude mcp list,Codex 则检查 ~/.codex/config.toml。发现陌生 MCP server 后,原文建议移除它、轮换可能被读取的 token 和 API key,并追查来源文件、近期 shell 历史及全局安装包。
我的判断
我赞同把指令文件当作需要审查的项目资产,也赞同优先保留审批、沙箱和凭证隔离。与单纯要求模型「忽略恶意指令」相比,这些措施能直接约束执行权限和可接触的数据,防护位置更靠近实际损害。
但原文有两处判断需要收紧。
首先,「代理无法区分用户指令和文件文本」说得过满。这里展示的是不可信文本可能影响代理决策,并不足以证明所有产品、所有配置都没有来源区分。
其次,「保留护栏就能消除大部分风险」没有对照数据支撑。原文引用的 IDC 分析师也把研究定位为可信的早期预警,而非广泛利用的证据,成功率尚未独立核验。作者的八项建议有实用价值,但不是经过统一测试的效果排名。
研究测试了 Codex 和 Claude Code。对 Cursor、Copilot、Gemini CLI,原文给出的是同类风险推断,不能写成它们都已被同样攻破。