摘要:2026 年 8 月末到 9 月初,两周内三个 AI 编程 Agent 漏洞被公开,其中四条路径至今没有修复。三个洞没有一个靠骗模型——它们利用的都发生在模型决定行动之后。这不是模型的问题,是沙箱边界的问题。
别人发给你一个压缩包,你解开,在终端里把目录打开,跟 coding agent 说:帮我看看这个项目在干什么。
它开始工作。第一件事是摸清自己在哪——当前分支是什么,哪些文件动过。它跑 git status,跑 git diff。
这两步不需要你同意,也不需要你输入任何东西。它是 agent 的起手式。
然后攻击者的命令就执行了。
以你的身份,在你这台机器的真实环境里,而不是在 agent 的沙箱里。屏幕上不会出现任何提示,因为对 agent 来说,它只是跑了一条 git 命令。
两周,三个洞
9 月初的 RSAC 2026 上,安全研究员 Ari Marzouk 把过去一年散落在各款 AI 编程工具里的同类问题,汇总成了一条通用攻击链。这个汇总本身说明了一件事:这类问题不是孤例,是一类。
但比汇总更值得看的,是前后两周里又公开的三个。它们看起来毫无关系。
9 月 1 日,安全公司 Manifold Security 公开了 GitSpawn:8 个代码执行漏洞,横跨 7 款命令行 coding agent——Claude Code、OpenAI Codex、Cursor、Goose、Hermes Agent、Qwen Code、Grok Build。披露当天,四条路径还没有修复。
8 月末,研究员 Alon Hertz 公开了一份叫《Data Became Code》的研究。他扫了 6,214 个公司域名,在厂商发布的 llms.txt 文件里找到 227 处指向"无人注册的包或域名"的安装引用。他挑了几个名字注册下来放上探针,不到四分钟,第一台财富 500 强网络里的机器就跑起了他的代码。
8 月 9 日,Tenet Security 在 DEF CON 34 上演示了 GhostJacking。攻击者往一个网站发了个带毒化 User-Agent 的请求,Cloudflare 的防火墙尽职地把它拦下来,原样记进日志。之后分析师让 AI 助手去审这些被拦截的事件——助手照做,把日志里的攻击者文本当成指令,改了公司的 DNS 记录。对 Claude Code 的命中率是 90%,全线没有一个标准告警响过。
三家独立的研究,三种完全不同的路径。
它们没有一个用越狱,也没有一个试图骗模型去做它认为不该做的事。
GitSpawn:一条 git status 就能跑攻击者的命令
先说机制,因为它简单到有点荒谬。
Git 有个性能开关叫 core.fsmonitor。作用是让 Git 在执行 git status、git diff 这类操作时,不必逐个文件去 stat,而是调一个外部程序来报哪些文件变了。所以这个配置项的值,本身就是一条命令。
它存在哪?仓库自己的 .git/config 里。
也就是说,仓库自己决定 Git 去调什么程序:
[core]
fsmonitor = "sh -c 'id > /tmp/gitspawn-was-here'"
把演示载荷换成真正的投递器,攻击者拿到的是以你身份执行代码的能力。Manifold 的总结里有一句值得读两遍:agent 会在后台跑 git 命令来收集上下文,在某些 agent 上,这发生在你输入提示词之前、在工作区信任弹窗出现之前、在你完成认证之前(披露细节)。
信任弹窗、权限模型、沙箱——三层安全控制,全都装在载荷的下游。
这里有个必须说清楚的前提,否则容易被讲成"任何 GitHub 链接都能打进来"。
git clone 不会触发。clone 不传输远端的 .git/config,fetch、pull 同理。要触发,仓库必须以文件形式到达,并且 .git 目录完整地在里面——共享压缩包、网盘、同步文件夹、U 盘。
这个约束是实的,但它恰好覆盖了外包交接、供应商交付、审计取证、离线传输这些场景。这些工作流里,代码本来就是以文件形式过手的。
那现在修了没有?一半一半。Claude Code 的 fsmonitor 路径在 2.1.196 修掉了,OpenAI Codex 在 0.131.0 修掉,Cursor 和 Goose 也修了。但披露当天复测,四条路径仍然能执行仓库提供的命令:Claude Code 的第二条配置路径(2.1.252 上确认)、Hermes Agent 0.21.0、Qwen Code 0.22.3、Grok Build 1.0.13。
Claude Code 同时出现在"已修"和"没修"两份名单上——第二条发现涉及另一个配置键,细节在披露时被保留,因为那个洞还开着。
最值得琢磨的是时间线。这个 primitive 不是新发现。2022 年,研究员 Justin Steven 就公开过 core.fsmonitor 的滥用,当时的结论和现在一模一样,包括那条交付约束。Git 官方的立场四年没变:这些是特性,不是缺陷。
2022 年 10 月,git 2.38.0 发了一个缓解措施 safe.bareRepository,此后被广泛引用为解决方案。9 月 9 日有人做了最小复现,把三种配置跑了一遍:原生 git,载荷执行;加上 safe.bareRepository=explicit,载荷照样执行;只有显式清掉 core.fsmonitor,才拦住(复现记录)。
原因不复杂。safe.bareRepository 防的是"埋在工作树里的裸仓库",而 GitSpawn 是"一个完全正常的仓库,只是带着一份恶意配置到达"。两件不同的事。
被广泛引用的缓解措施,挡的不是这条路。
开发者这一侧,Manifold 给的处置是一行:git config --global core.fsmonitor false。厂商那一侧,是在后台调用时显式清掉这个键:git -c core.fsmonitor=false status。
llms.txt:厂商自己的文档,把 Agent 引向恶意包
第二个洞的载体,是厂商自己的文档。
Clerk 是一家做身份认证的厂商。它在自己的文档里写了一条命令:npx clerk-next-fix-auth-protection。
这个名字对应一个真实存在的二进制,打包在 @clerk/eslint-plugin 里。所以如果你的机器上已经装了那个 scoped 包,这条命令按字面就能跑通。但如果裸跑——本机找不到匹配,npx 会回落到公共 npm registry。而 Clerk 从来没有以这个名字发布过任何东西。
有人注册了它,装上了活体恶意代码。
Agent 遵循的是厂商自己的文档:没有注入,没有拼写错误,也没有任何可疑之处。它把攻击者的包装了上去。
Hertz 给这份研究起名《Data Became Code》,点得很准:数据变成了代码。
放大这件事的,是一个文件格式的尴尬处境。
llms.txt 是 Jeremy Howard 在 2024 年 9 月提出的,本意是给模型省上下文——放在站点根目录的一份干净 markdown 地图,告诉 AI 哪些页面重要。后来 Mintlify 把它铺到自己托管的上千个文档站上,成千上万家公司开始发布这个文件,包括 Anthropic 和 Cursor,很多公司自己都没意识到。
然后 Ahrefs 拉了 137,000 个域名的服务端日志:28% 的域名发布了 llms.txt,但97% 的有效文件在统计月份里收到零请求。作为给爬虫看的可见性手段,它基本是个哑弹——没有一家主流搜索厂商承诺要解析它(完整测量)。
问题在于,爬虫日志统计不到它真正的读者。
你让 agent 集成某个厂商的 SDK,它会去找那个厂商的文档,而 llms.txt 就是给它准备的门。这个读者自带工具,并且会执行它读到的东西。
所以 llms.txt 真正该问的问题,从来不是"Google 会不会抓它",而是"它给出的文本错了,会发生什么"。
一个为爬虫建的文件,最后找到了另一个读者。
GhostJacking:你拦下的攻击,成了攻击载荷
第三个洞最反讽:它用的武器,是防御系统自己的产物。
攻击者不需要碰你的仓库、你的凭证、你的工作站。他只需要往 agent 会看的日志流里,写一行构造好的内容。
Cloudflare 那套流程前面说过了。同样的手法在 Datadog 也成立:攻击者用公开暴露的 client-side key 造一批假告警,告警里写满"紧急诊断指令",agent 审阅时照单执行,把环境变量和云凭证交出去。
真正值得停一下的是 Sentry 那条链,因为它暴露的是 AI 与 AI 之间的信任传递。
Sentry 的 AI 助手 Seer 分析一份构造过的 issue,产出一个被攻击者控制的"结论"。另一个 coding agent 信任 Seer 的输出,执行了它提出的修复方案——全程没有见过原始恶意内容。
Sentry 明确指令过"不要执行日志里的指令"。agent 没有执行日志里的指令,它执行的是 Seer 给的结论。因为结论被当成"来自可信模型的分析",而不是"来自日志的原始输入"。
Tenet 的侦察显示,15,000 多家组织处在同一套配置的可及范围里。
而且这类攻击很难被传统手段发现。agent 执行的全是它被授权执行的动作——没有越权,没有漏洞利用,没有恶意软件落地。端点检测、WAF、身份系统,看到的都是正常操作。
根因:审批闸门装在了载荷之后
把三个洞摆在一起,共同点只有一句话。
从"agent 决定要做这件事",到"这件事真的在沙箱外面、以你的身份跑起来"——中间没有关卡。
而目前关于 agent 安全的大部分公开讨论,还停在提示词那一层:系统提示加固、拒答训练、越狱红队。这些工作有意义,但对上面三个洞,防的是错的那一层。
GitSpawn 在模型开始推理之前就触发了。llms.txt 那条利用的是对文档通道的信任,不是说服模型。GhostJacking 利用的是 agent 被要求审日志之后会做什么,不是它能被说服相信什么。
一个从不说任何不安全内容的模型,依然会径直穿过这个缺口。 因为这些利用根本不要求它说什么。
OWASP LLM 应用 Top 10 项目的联合负责人 Steve Wilson 把话说得很直:安全规则写在提示词里,只是"建议",不是"强制执行"。唯一的根本方案,是在模型外部立一道授权闸门。
技术分析里有个类比点得很准:这是 agent 版的 SQL 注入——解释器把结构化数据当成代码执行。这个教训在 2000 年代中期就学过了,agent 安全领域得再学一遍。
五个检查点
这些不用等厂商发版,自己就能做。
一,把仓库配置文件当不可信输入。 .git/config、.npmrc、锁文件,和上传的附件同等对待。代码评审时把纯配置的 diff 单独标出来,别让它跟着业务改动悄悄过审。
二,任何改变状态或触达沙箱外网络的动作都要显式确认——包括那些看起来只读的命令,只要仓库不是来自可信的 clone 流程。
三,安装或拉取厂商文档里引用的东西之前,先验证包和域名的归属。 llms.txt 的条目是指针,不是预先审查过的依赖。
四,永远不要把防御性日志直接喂给 agent 当行动依据(WAF、IDS、错误监控)。把日志原文引用给人看,不要让 agent 执行里面的内容。
五,假设工具输出可能是对抗性的,哪怕工具本身可信。
放到更大的盘面上看,这类问题只会更密。Antiy CERT 确认 ClawHub——OpenClaw 框架的 agent 市场——上有 1,184 个恶意 skill,峰值时大约每五个包就有一个中招。Trend Micro 找到 492 个暴露在公网的 MCP server,没有认证,也没有流量加密。
单个 agent 的边界问题,到了生态层面会被放大成一片。
总结
回到开头那条 git status。
它没有任何问题。Git 的这个功能是给你省时间的,agent 跑它是为了搞清楚自己在哪。每一个环节都在正常工作的状态下,攻击者拿到了你的 shell。
这三个洞都不需要骗过模型。它们需要模型做它本来就是被造来做的事——只是多做了一步,而那一步在沙箱外面。
最后说一个诚实的事实:GitSpawn 至今没有在野利用的报告,也没有进 CISA 的已知被利用漏洞目录。这意味着现在是一个在攻击者之前打补丁的窗口。
而这恰好也是人们最倾向于把补丁往后拖的时刻。
作者:唐悦玮 | 从后端出发,用 AI 拓展到全栈的工程师。