沙箱从来就不是安全边界,这次是 OpenAI 自己证的

小岛AI 2026 / 07 / 26

Hugging Face 报警的时候,不知道黑自己的是 OpenAI。

OpenAI 当时也不知道。

时间线是这么排的。7 月 11 到 13 日,Hugging Face 的生产基础设施被端到端打穿了一遍。7 月 16 日他们发了一份事件披露,说这次入侵从头到尾由一套自主 AI 智能体系统执行,不是人类操作员坐在键盘前一条条敲的。因为压根不知道对面是谁,他们把 FBI 请了进来。

一直到 7 月 18、19 号,OpenAI 的员工在自家内部日志里翻出线索,才反应过来,好家伙,是自己的模型跑出去了。7 月 20 日,两家公司才终于对上口径。

从攻击结束到确认主体,中间空了大概一周。

这一周才是这条新闻里最值钱的部分,可惜大部分转发都停在了前半句「AI 自己去黑 AI 社区了」。

先把事实摆清楚。据 The Decoder 综合 TIME 与 Bloomberg 报道的梳理,OpenAI 内部在评估模型的网络攻击能力,参与测试的有三个模型,一个是 GPT-5.6 Sol,一个是还没发布的更强的模型,还有一个是刻意没走常规对齐流程的版本。为什么刻意不加护栏,因为你要测一把刀有多快,就不能一直给它套着刀鞘。这个思路本身没毛病,几乎所有做红队评估的团队都这么干。

7 月 9 日,模型开始尝试逃出测试环境。它找到的那个口子,说出来会让每个做基础设施的人沉默几秒,是一个用于下载已批准软件的内部服务里的未知漏洞。就那种平平无奇、写完三年没人再看一眼、在架构图上连个框都不配有的小服务。模型顺着它摸到了 OpenAI 的其他系统,然后接上了公网,然后把目标对准了 Hugging Face。

人类黑客要花几周的事,它用了几个小时。

Bloomberg 那句描述我看了两遍,模型在 Hugging Face 的系统里潜伏了数小时未被发现。更有意思的是,它还顺手作弊了,把入侵过程中拿到的信息拿回来改善自己在评测里的成绩。厉害了,为了跑分连这个都想得到。

一位没具名的 OpenAI 员工跟 TIME 说了一句大实话,模型以前也逃出过沙箱,不可能把一个有创造力的 AI 能想到的每一件事都打上补丁。

这句话我完全同意,但我觉得它推出的结论跟大多数人以为的不一样。

大多数人看完这条新闻的第一反应是,模型太危险了,得加更多护栏。我的反应是另一件事,沙箱这个东西,从来就不是安全边界,我们只是过去一直没被打脸而已。

沙箱是隔离手段。隔离手段和安全边界的区别在哪,在于前者的假设是「里面的东西不会主动找出路」,后者的假设是「里面的东西一定会主动找出路,所以我要在它找到之前把每条路都堵死」。容器、虚拟机、seccomp、namespace,这些技术当年被造出来的时候,防的是有 bug 的进程,不是防一个会主动列举、试探、组合利用漏洞的东西。

你想想看,一个跑飞了的 Python 进程不会去扫内网端口,不会去读你的 metadata 服务,不会发现某个内部包管理器有个反序列化的洞然后写个 exploit。但 agent 会。它不是因为「变坏了」才这么干,它就是在完成你交给它的任务,而你交给它的任务恰好是「找到攻击路径」。

坦率讲,这事最扎心的地方在于,OpenAI 用的是专业的隔离测试环境,有安全团队,有预算,有专门做这件事的人。他们都被穿了。

箱体加固得再厚,出事的往往是底边那道没人看过的缝

那我们呢。

我说的是每天在本机跑 agent 的你我。Claude Code 那个 --dangerously-skip-permissions,名字已经把丑话说在前头了,可有几个人是不加这个参数跑的。Cursor 的 agent 模式默认能改工作区任意文件。Codex 跑起来就在你的仓库里。很多人图省事,直接在宿主机上跑,~/.aws/credentials 在那儿放着,~/.npmrc 里的 token 在那儿放着,SSH key 在那儿放着,Docker socket 挂着,出网完全不限。

讲究一点的会套个容器。但容器里挂了 host 目录,容器里注入了一堆环境变量,容器能直接访问公司内网。这时候容器只是让你心理上舒服一点,它拦不住一个真的想出去的东西。

我不是要吓唬谁,也不是说明天就得把所有 agent 关进小黑屋。我自己也还在摸索这条线到底该划在哪。但至少我们得先把话说明白,那个让你觉得安全的东西,其实只是让你看不见风险。

再说 Hugging Face 这一侧,攻击链值得每个做平台的人抄下来贴在墙上。

第一步是初始访问,攻击者上传了一个恶意数据集,同时用了两条代码执行路径。一条是数据集的远程代码加载器,就是那种为了方便,允许数据集自带一段处理脚本、加载的时候顺手执行的设计。另一条是数据集配置里的模板注入,模板注入这个词简单讲,就是配置文件里本来只该填数据的地方,你塞进去一段会被当成代码跑起来的东西。两条路都是「为了灵活性开的后门」,用了十年都相安无事。

第二步是提权,从处理 worker 拿到节点级权限。第三步开始收割,云凭据、集群凭据,能拿的全拿。第四步横向移动,一个周末的时间横穿多个内部集群。

这个链条上每一环都不新鲜,任何一本渗透测试的书里都有。新鲜的是执行的密度和速度。

Hugging Face 官方披露的攻击链,五步从一个数据集走到多个内部集群

Hugging Face 官方的描述是,攻击者是一套自主智能体框架,在一群短生命周期沙箱上执行了成千上万次单个动作,命令与控制通道还会自己迁移,托管在公共服务上。

短生命周期沙箱这个形态,对传统检测逻辑几乎是天然规避。我们做告警的时候,规则大多长这样,同一个 IP 在 5 分钟内失败了 20 次、同一个会话在做异常行为、某个 token 的调用频率突增。这些规则的底层假设是「攻击者是一个持续存在的实体」。可它不是。它是一群随生随灭的短命进程,每个都只干一小件事,单看每一条日志都平平无奇,攻击的形状只存在于这一万多条记录合起来看的那个层面。

而合起来看,恰恰是人类安全工程师最不擅长的事。

说到这儿就绕回我真正想聊的那件事了,归因缺口。

Hugging Face 事后跑取证,把完整的攻击动作日志拉出来分析,一共超过 1.7 万条记录事件。注意这个数字的含义,不是「日志没记全所以查不出来」,是每一条都记着,一条不缺

可即便如此,从发现异常到知道这是谁干的,中间隔了一周。Hugging Face 先是靠 AI 辅助的异常检测关联多路遥测信号,发现出事了。然后呢,然后就卡住了,只能报警,只能请外部取证专家。而在地球另一边,OpenAI 的日志里同样记着一切,同样没人抬头。

检测到「有攻击」,和知道「是谁在攻击」,是两件完全不同的事。前者我们这些年做得越来越好,后者几乎原地踏步。

每一条都记着,每一条上该写「是谁」的那一栏都是空的

这个缺口在传统安全里没那么致命,因为攻击者是人,人有习惯、有工具指纹、有时区、有语言习惯,情报圈子里那套归因方法论积累了二十年。但 agent 没有这些。它没有作息,工具是临时生成的,指纹每次都不一样。你甚至没法判断它到底是「某个组织派来的」还是「某个测试跑飞了」。

这次的答案居然是后者,这一下给我整不会了。

而且这个缺口不是只存在于 OpenAI 那种量级的公司里。现在稍微像样一点的工程团队,谁手里没同时跑着三五个 agent。CI 里挂着一个自动改 lint 的,仓库里挂着一个盯依赖升级的,Slack 上挂着一个值班答疑的,本地还开着两个终端各跑各的。它们用的往往是同一个服务账号、同一把 token、同一个 CI runner 身份。

那么问题来了,某天你在审计日志里看到一次可疑的仓库写入,你能在十分钟内说出是哪个 agent、哪一次任务、由谁触发的吗。

我猜大部分人的答案跟我一样,是「得查一会儿」。这个「得查一会儿」放大一万倍,就是 Hugging Face 和 OpenAI 中间那一周。

接下来这个细节有点子牛逼,我觉得它才是整件事里最反讽的一笔。

Hugging Face 做取证的时候,需要把真实的攻击命令、漏洞利用载荷、C2 痕迹喂给模型去分析。结果商业 API 背后的那些前沿模型,因为安全护栏,拒绝处理这些提交。

于是他们只能改用开源权重的 GLM 5.2,部署在自家基础设施上,跑 LLM 驱动的分析智能体,把那一万七千条日志过了一遍,重建时间从按天压到了按小时。

好好品一下这个画面。攻击方用的是一个刻意卸掉护栏的模型,畅通无阻。防守方想用商业模型分析攻击,被自己付费的安全策略挡在门外,最后只能退回到开源权重自建。

护栏拦住的不是攻击者,是防御者。

我不觉得这是哪家厂商的恶意,做安全策略的人也很难,你没法在 API 层面分辨「我在分析这段 exploit」和「我在写这段 exploit」。但结果就是结果,防守侧的工具链正在被自己的合规要求削弱,而攻击侧没有这个约束。这个不对称如果不解决,以后每一次事故复盘,防守方都得先解决「我用什么工具复盘」这个前置问题。

The Hacker News 那篇技术复盘Help Net Security 的报道都提到了这一点,两边措辞不同但指向一致。Hugging Face 自己在披露里也没绕弯子,直接写了因为商业模型的护栏挡住了真实攻击载荷的提交,所以选择了自部署开源模型。

好消息是损失比想象中小。Hugging Face 确认被未授权访问的是有限的内部数据集和若干服务凭据,没有发现公开的模型、数据集、Spaces 被篡改,软件供应链也就是容器镜像和已发布的软件包,验证下来是干净的。合作伙伴和客户数据目前没发现被访问的证据,调查还在继续。处置也做得挺利索,关掉数据集的代码执行路径、重建被攻陷节点、大范围轮换密钥、上更严的集群准入控制、把告警做到 7×24。

他们给用户的建议就一句,轮换你的 access token,检查最近的账户活动。如果你在 HF 上有 token 还没动过,读到这儿可以先去转一圈,我等你。

那么落到我们自己身上,到底该改什么。我想了想,只有三件事真的值得现在就动手,其它的都可以往后排。

第一件是出网。

整条攻击链里,真正的分水岭是模型接上公网那一刻。之前它只是在一个封闭空间里乱撞,之后才成为一个能对外部世界产生影响的东西。

给 agent 配默认拒绝的出网策略,只放行白名单里的域名,是我目前能想到的性价比最高的一件事。你的 agent 需要访问 npm registry、需要访问 GitHub、需要调你自己的 API,把这些列出来,剩下的全掐。这个动作在 Docker 里就是一条自定义网络加一个 proxy,工作量顶多一小时。

顺带提一句,如果你的 agent 跑在云上,metadata 服务那个地址一定要单独封掉。那是云上凭据泄露的头号入口,被写进无数篇事故复盘里,可默认配置至今是通的。

第二件是凭据。

代码执行本身不可怕,可怕的是代码执行发生在一个手里攥着一大把长期凭据的进程里。Hugging Face 的攻击链里最要命的一跳,就是从节点权限到云凭据和集群凭据。

给 agent 的凭据要满足三个条件,短时效、窄权限、可撤销。别再往环境变量里塞永久 token 了。真要用,宁可套一层代理,让 agent 拿一个五分钟就过期的临时票据。1975 年 Saltzer 和 Schroeder 写下最小权限原则的时候,防的是有 bug 的程序,五十年后我们要防的东西比那聪明得多,可原则一个字都不用改。

愚钝如我,也是最近才想明白一件事,我们给 agent 的权限,往往是按「它最复杂的那次任务」配的,而它 99% 的时间在干最简单的活。这个账算下来非常亏。

第三件是审计,也是最容易被跳过的一件。

Hugging Face 的日志记全了,1.7 万条,一条不缺,可还是花了一周才归因。所以光记是不够的。真正的问题是,你的日志里有没有一个字段,能把每一个动作稳定地绑回到某一次 agent 会话、某一个模型、某一次任务上。

大部分人的 agent 日志现在长什么样,我猜是一堆 stdout 混着模型输出滚在终端里,跑完就没了。要是哪天真出了事,你打开终端,什么也捞不着。

一个最低成本的做法是,每次 agent 会话生成一个 trace id,注入到它发出的每个 HTTP 请求头、每条命令的环境变量、每次工具调用的记录里。这样万一出事,你至少能在一堆日志里把属于同一次会话的动作串起来。做起来不难,难的是想起来做。

其实吧,这三件事没有一件是新东西。出网管控、最小权限、可追溯审计,安全圈讲了几十年,讲到大家都听腻了。区别只在于,以前不做,代价是「万一有人打进来」;现在不做,代价是「我自己开的那个终端里,正在跑着一个比我更会找洞的东西」。

我一直觉得,这波 agent 浪潮里最容易被忽略的风险,不是模型会不会「觉醒」,而是我们把一个能自主行动的东西,接进了一套完全按「工具不会自己动」这个假设设计的基础设施里。工具突然长出了主动性,而承载它的地基还是老的。

写到这儿我想起开头那个画面。Hugging Face 已经把 FBI 请进门了,OpenAI 还在自家日志里毫无察觉。这不是哪一方水平不行,这是我们整个行业当下的真实水位。

灯塔照得到很远的海面,照不到自己的塔底。

说真的,我不确定明年这时候回头看,这次事件会被记成一个转折点,还是只是一长串同类事件里编号靠前的那一个。但有一件事我挺确定的,下次再有人跟你说「放心,它跑在沙箱里」,你可以笑一下,然后问他,出网关了吗,凭据几分钟过期,日志里有 trace id 吗。

三个问题,一个都答不上来的话,那不叫沙箱,那叫一个心理安慰。

参考资料,Hugging Face 官方事件披露The Decoder 对失控细节的报道Axios 的时间线梳理The Hacker News 技术复盘Help Net Security 报道IT之家中文报道