最后一步是一句提示
9 月 18 日,Hacktron 公开了他们一路打进 OpenAI 私有单一仓库的链条。起点是一张上传到公开论坛的图片,以及某个图像解码器里的堆溢出,而它在上游的修复没有带任何 CVE。终点是研究人员向某位员工的 Codex 账号发出一句提示,智能体便开了那个 pull request。没有注入,也没有任何东西失灵;智能体只是照着握有会话的人所要求的去做。Bromure Agentic Coding 把这次写入的决定放在会话之外,放在你的 Mac 上。
这条链的最后一步不需要任何漏洞利用。研究人员手里握着某位员工的编码智能体,于是他 们请它在私有单一仓库里开一个 pull request,它就开了一个。
7 月 25 日 UTC 早上六点,Hacktron 的三位研究人员已经在 OpenAI 的公开社区论坛上拿到
了代码执行。到下午早些时候,一个编号 1186742 的 pull request 已经躺在私有单一仓库
openai/openai 里,而他们没有为此写下一行代码。他们问了一个智能体,智能体就把它提
交了。
Hacktron 在 9 月 18 日公开了这条链, 值得一环一环读下去,因为每一环都很平常。研究人员是 Harsh Jaiswal、Mohan Pedhapati 和 Rahul Maini。 The Hacker News 第二天做了报道。
一张图、一次转换,和一个解析器
入口是论坛的图片上传。Discourse 用一个叫 FastImage 的 Ruby 库检查上传的图片,它只读
文件头中足以判断尺寸与格式的部分。FastImage 不懂 HEIF,也就是 iPhone 照片抵达时所用
的容器,于是 Discourse 把这类文件交给 ImageMagick 的 magick 命令去转换。ImageMagick
用 libheif 解码 HEIC,而那是 C 写的。
入口条件就这么多。一种安全检查器不认识的格式被送去转换器,而转换器调用了一个用 「长度字段畸形即内存安全问题」的语言写成的解析器。Hacktron 在 HEIC 解码里找到一个堆 缓冲区溢出,并由此拿到越界读取与写入的原语。
文书工作比这个缺陷本身更糟。上游前一年就修好了那个溢出,却从未把那次提交标为安全修
复。它没有 CVE、没有公告,也没有任何依赖扫描器读得到的变更日志,所以 Debian 从未回
移,而 Discourse 的 Docker 镜像就这样带着完好无损的缺陷,在 Debian 12 上发布
libheif 1.19.7。全世界没有任何扫描器有理由标记那个版本。Debian 后来发布了
DSA-6417-1,这个问题如今挂着 CVE-2026-32882——在有人真的利用它之后才分配的编号。
没人报过的缺陷,你扫不出来。你能事先决定的,是解析器倒下时,它站在什么里面。
漏洞利用花了一个晚上
Hacktron 从 7 月 23 日开始看那条上传流水线。7 月 24 日,他们用 Claude Opus 4.8 去攻 那个溢出;按他们的说法,模型在好几个会话里都很吃力,做不出任何能对付地址空间布局随 机化的东西——那是把进程的内存布局打乱、让攻击者无法预测东西在哪里的防御。把堆溢出变 成在 ASLR 之下依然可靠的执行,正是难的那一部分,也正是这类研究会卡上一周的地方。
Anthropic 当晚发布了 Opus 5。Hacktron 开了一个全新的会话,三小时后就有了一个能对本
机 Mac 运行的 ARM64 漏洞利用。他们请模型把它移植到 Discourse 所用的 x86-64 与
jemalloc 配置,并在第二天早上六点确认了通过图片上传达成的本机代码执行。随后他们让
Claude 对自家的 Discourse Cloud 实例跑自主循环。十点时,它在那里也拿到了代码执行,
并读出 /etc/hosts 作为证明。
他们对这件事的意义很谨慎,而这个保留应当放进任何一种解读里:
这并非完全自主的黑客行动。要引导会话、验证结果并处理披露,人类的专业知识依然不可 或缺。
说得对。三位熟练的研究人员把工具对准了目标,而他们的本事并没有一夜之间改变。缺陷也 没变。在那两个会话之间,唯一的新变量是模型,而它把一件屡试屡败的利用工作压到了三小 时。这件事所属的整场行动,让 Hacktron 花掉不到三千美元的 token 费用,以及几个小时的 人力。
这个数字就是规划的输入值。一个从未拿到 CVE、蹲在某个文件转换器传递依赖里的缺陷,如 今只要一台笔记本的价钱就能变成可靠的原语。等公告是一种指望,而没有人能靠把变更日志 读得更快来跑赢那个时钟。
最后一步是一句提示
论坛上的代码执行,并没有给 Hacktron 任何 OpenAI 在意的东西。做到那件事的是第二个问 题。OpenAI 把单点登录接成了这样:只要论坛会话被攻陷,任何用过论坛的员工,其 ChatGPT 与 Codex 账号就会在毫无交互的情况下被接管。用 Hacktron 的话说,正是这个 SSO 问题,把 论坛的失守变成了对 ChatGPT 与 Codex 的访问。
某位员工的 Codex 连着公司的 GitHub 组织,于是研究人员做了最显而易见的事。他们向那个
账号发出一句提示,请它在内部单一仓库开一个 pull request,PR 1186742 便出现在
openai/openai 里。接着他们就收手,没有去读任何源码,提交了报告。
把这一步再读一遍。某个握有有效会话的人请智能体做一件平常的事,智能体就用它本来就有 的写入权限做了。没有注入,没有越狱,没有畸形输入。所有人建起来的每一道控制,都坐在 那个会话的后面:登录、组织成员身份、仓库权限。攻击者一旦握有那个会话,就等于全都握 有。
编码智能体是一份长期有效的仓库写入授权,附着在一段对话上。任何够得着那段对话的人,
都继承那份授权。浏览器里的 Codex 如此,笔记本上的 Claude Code、Codex CLI 或 Gemini
CLI 也如此——在那里,智能体在 ~/.git-credentials 里带着真的 ghp_ 令牌,在环境里
带着真的 GH_TOKEN。在笔记本上,入口还会变多:仓库里一个被投毒的文件、一条 issue
评论、包的 postinstall 脚本、一个被劫持的终端。
OpenAI 大约用十四小时修补了论坛。报告在那天早上送进去,OpenAI 在同一天 UTC 22:49 确 认修复完成。Discourse 在周末推出自己的修复,并于 7 月 28 日发布公告 GHSA-vhm9-85gw-x335,赏金共计 6,500 美元。这个形状里落在你自己桌上的那一块,是智能 体。
写入是在哪里被决定的
Bromure Agentic Coding 把「谁可以 push」的答案留在你的 Mac 上,留在智能体的会话 之外,因为会话正是攻击者想够到的东西。那里会发生两件事。
第一,智能体的环境里没有任何可继承的令牌。工作区的虚拟机拿到的是一个诱饵:ghp_ 加
上 36 个字符,形状做得让 gh 和 git 都不会有意见,并且由你真正的令牌经 HKDF-SHA256
与每次安装专属的盐派生而来,因此它在不同会话之间看起来从不轮换。你真正的令牌加密存
放在宿主机上,宿主机代理会在请求离开虚拟机之后,于线路上把它替换进去,而且只在目的
地与该令牌所签发的主机相符时才替换。正如手册所说:虚拟机内部没有任何文件、环境变量
或进程会含有真的 API 密钥、OAuth 令牌、AWS 机密或 SSH 私钥。把那个诱饵带到它不该去的
地方,代理会回 HTTP 451 而一个字节都不转发,并暂停虚拟机,在 Security Timeline 写下
一行红色记录。
第二件,正是这个故事所要的。每一份 git 托管服务的凭据都带着一条写入策略,在
Guardrails 面板里按工作区设置,而新工作区的默认值是写入前先询问。读取一声不响就
过去了。git push 在线路上以 git-receive-pack 的样子抵达,算作写入;对 pull
request API 的 POST 也一样。当其中一个抵达时,代理会扣住请求,在你的 Mac 上弹出一
个对话框,上面载的是原样的操作而不是摘要:方法与路径。你可以选允许 15 分钟、
允许一次、允许本会话其余时间,或不允许。拒绝会以一个普通的 API 错误抵达
智能体,它能据此回报,而不是一条挂住的连接。
这个面板自己对运行位置的描述,就是最要紧的那一句:在代理上强制执行,因此虚拟机里被 攻陷的智能体无法绕过。
不管是谁在驾驶智能体——你、埋在 fixture 文件里的提示注入,或者某个握着从你手上夺走 的会话的人——写入都从同一个代理出去,并以同一种方式被归类。你 Mac 上那个对话框就是授 权,而握有你会话的攻击者,并没有握有你的 Mac。
解析器的问题也会来到你的桌上
这条链的另一半同样可以一般化,而把它算进成本里的人并不多。
编码智能体整天都在读自己没写过的文件:跟着仓库一起来的测试 fixture、附在缺陷报告里
的图片、你贴进对话里的截图、一份规格的 PDF、从发布页抓下来的 tarball、一个字体文件、
前端要播放的视频。处理这些东西,意味着去调用 magick、ffmpeg、pdftotext 或
unzip,或者绑进 Python 的某个图像库,而它们每一个都是吃着别人选定的字节的 C 或
C++ 解析器。那正是让一次论坛上传一路抵达 libheif 的条件。智能体碰上这个条件的次数
比你多,因为它在打开任何东西之前从不犹豫。
检测在这里没有答案。libheif 的缺陷在最要紧的那一刻没有 CVE,所以没有任何扫描器、允 许清单或版本锁定会说半个字。你能挑的只有爆炸半径,仅此而已。
在 Bromure 工作区里,那个解码器跑在 Apple Virtualization.framework 之下的 Ubuntu 客
户机中,那是一道 hypervisor 边界而不是进程沙箱,而且那个客户机被 Bromure 在架构上就
当作不可信。图像解析器里的堆溢出,为攻击者买到的是一台 Linux 虚拟机里的 shell:它的
凭据是诱饵,而它通往互联网的路径是宿主机上一组有次序的规则。虚拟交换机按目的地 IP
与从 DNS 嗅探到的主机名,在 TCP 与 UDP 上匹配那组规则,代理再按 TLS 服务器名与 HTTP
方法匹配一次。把未命中的流量设为拒绝,那个 shell 手上就只剩一张允许清单,别无其
他。交换机把 :80 与 :443 改道进代理本身,所以没有任何代理变量可供 shell 取消。规
则的改动不必重启就会抵达进行中的会话,而每一个判定都会落成 Security Timeline 里的一
行 Firewall 记录。
就当解析器一定会倒
这个缺陷在最要紧的那一刻没有 CVE。按解码器会输来规划,并事先决定它倒下时站在什 么里面。
会话不等于授权
任何够得着那段对话的人,都继承智能体的写入权限。把 push 的决定放到对话够不着的 地方。
别在虚拟机里留下可偷的东西
一个工具会接受的诱饵,在上游一文不值;对把它带去别处的攻击者来说,更是连一文都 不如。
给漏洞利用标个价
三小时,加上几千美元的 token。把公告读得更快,回答不了这个数字。
Hacktron 的文章是好研究,也诚实交代了其中有多少仍得靠人类掌舵。明年还会成立的,是结 尾那一段。这条链上的每一道防御,都坐在一个身份的后面;而当带着那个身份的会话易手之 后,它们就全都不再有任何意见了。有人请智能体做事,智能体就照做了。
如果你的智能体能 push,那就问问 push 的权限住在哪里,以及一个把智能体所有东西都夺走 的攻击者,会不会连那份权限一起夺走。在笔记本上,他会。把这一个决定搬离智能体所在的 机器,这条链的最后一步就有了可以停下来的地方。