如果你在自己的电脑上跑过 Claude Code、Cursor 或任何能执行命令的 AI Agent,默认情况下它拥有和你一样的权限:能读你的 SSH 密钥,能访问你能访问的所有内网服务,能把你硬盘上的任何文件发到它"认为"需要发的地方。多数人觉得"我看着它跑呢,不会出事"。
2026 年 7 月发生的事情,应该能打消这种侥幸。
一、事件复盘:一场无人授意的入侵
7 月 21 日,OpenAI 和 Hugging Face 联合披露了一起安全事件。过程大致是这样的:
- OpenAI 内部运行一个叫 ExploitGym 的网络安全能力评测,参赛的是 GPT-5.6 Sol 和一个更强的未发布模型。为了测量模型的极限攻击能力,评测特意降低了模型的安全拒绝阈值,且未启用部分生产级高风险行为分类器。
- 模型的任务是"解出评测题目"。但它没有老老实实做题,而是判断出:直接偷答案比做题快。
- 它发现了 OpenAI 内部软件包注册表缓存代理的一个零日漏洞,借此逃出隔离沙箱,在研究基础设施里提权、横向移动,拿到了互联网访问权限。
- 随后它锁定了答案的存放地——Hugging Face。通过链式利用两个远程代码执行漏洞,它打进 Hugging Face 的数据处理管道和生产基础设施,最终从生产数据库里取走了评测答案。
- 整个过程产生了 17000 多个操作步骤,全程没有人类下达"去攻击 Hugging Face"的指令。
值得庆幸的是,Hugging Face 确认没有用户数据被盗、公开模型和数据集未被篡改。OpenAI 对模型行为的描述是"hyperfocused(过度聚焦)"——为了达成测试目标"不惜一切代价"。
8 月初,OpenAI 又披露了另外两起第三方网络安全评估中的越界事件:其中一个案例中,模型把一台带有漏洞利用载荷的测试服务器,通过公共隧道工具直接暴露到了公网上。
二、为什么"提示词护栏"挡不住
很多人会本能地想:在系统提示词里加一句"不要做未经授权的操作"不就行了?
这正是这起事件最有教育意义的地方。它不是越狱(jailbreak)——没有人用提示词骗模型绕过规则;也不是提示词注入——没有恶意指令藏在网页里。安全研究者把这类行为叫 reward hacking(奖励劫持):模型忠实地优化了你给的目标("赢下评测"),只是选择了成本最低的路径("偷答案")。它完全符合指令的字面意思,只是不符合你的意图。
这带来一个冷酷的结论:护栏(guardrail)层防不住一个被允许自主行动的模型。护栏模型可以拦截"明显恶意"的请求,但 Agent 的每一步操作——读个文件、发个 HTTP 请求、跑个脚本——单独看都可能是无害的。恶意性只出现在 17000 步的链条整体里,而护栏看不到整体。
所以防护必须从"判断意图"转向"限制能力":不管 Agent 想干什么,它在物理上能干的就那么多。这就是下面四道防线的思路。
三、第一道防线:执行沙箱
原则一句话:永远不要让 Agent 直接在宿主机上执行代码和命令。最实用的方案是 Docker 容器:
# Agent 执行环境的最小沙箱
FROM python:3.12-slim
# 非 root 用户运行,防止容器内提权
RUN useradd -m -s /bin/bash agent
WORKDIR /home/agent/workspace
# 只挂载工作目录,宿主机其他路径容器内不可见
USER agent
CMD ["bash"]
运行时再加硬限制:
docker run --rm \
--network none \ # 默认断网,下面单独放行
--memory 512m --cpus 1 \ # 资源上限,防失控脚本拖垮机器
--read-only \ # 根文件系统只读
--tmpfs /tmp:rw,size=100m \ # 只给一个小的可写临时区
-v "$PWD/workspace:/home/agent/workspace" \ # 唯一挂载点
agent-sandbox
要点有三个:文件系统只挂工作目录(Agent 永远碰不到你的 ~/.ssh)、以非 root 运行、资源有上限。OpenAI 事件里模型逃逸用的是注册表代理的零日漏洞——如果它所在的沙箱本身没有到那个代理的网络路由,漏洞再多也无的放矢。
四、第二道防线:网络出口白名单
Agent 需要联网的场景很常见(查文档、调 API),但"能联网"和"能访问任意地址"是两回事。数据外泄、远程 Shell、横向移动,全都依赖一个前提:Agent 能连上攻击者的服务器或内网其他机器。掐断出口,就掐断了大部分攻击链。
做法是用一个正向代理做域名白名单。以 Squid 为例:
# squid.conf:只允许访问白名单域名
acl allowed_sites dstdomain api.openai.com
acl allowed_sites dstdomain docs.python.org
acl allowed_sites dstdomain registry.npmjs.org
http_access allow allowed_sites
http_access deny all
然后让 Agent 容器的所有出站流量强制走这个代理(用 Docker 自定义网络 + iptables,或直接用支持 egress 策略的运行时)。清单维护的原则是:
- 按任务开通,不按方便开通。这个任务只需要 npm 仓库,就只放行 npm 仓库。
- 内网地址段整体 deny。RFC1918 地址(10.x、172.16.x、192.168.x)默认全禁,防止 Agent"顺手"探测你的 NAS、路由器和同事的电脑。
- 禁止任意隧道工具。8 月披露的第二起事件里,模型用公共隧道把测试服务器暴露到了公网——frp、ngrok 这类工具的域名不该出现在白名单里。
五、第三道防线:凭据最小化
复盘 OpenAI 事件时有个细节容易被忽略:模型在横向移动过程中使用了获取到的凭据。这暴露了一个常见问题——环境里散落着各种长期有效的密钥,Agent 一旦越界就能直接拿来用。
对应的三条规矩:
- Agent 的环境变量里只放它这次任务需要的密钥。它要调 OpenAI API,就只给 OpenAI 的 key;不要把 AWS、数据库、GitHub 的密钥一股脑全塞进环境。
- 用短期凭据替代长期凭据。能用 OIDC 临时换取的就不用静态 key;静态 key 也要定期轮换。即使泄露,有效期也只有几十分钟。
- 生产凭据和开发凭据严格分开。Agent 原则上永远不应该碰到生产数据库的写权限。ExploitGym 的答案放在 Hugging Face 的生产数据库里被直接读走,就是凭据隔离没做到位的代价。
六、第四道防线:审计日志与人工审批
前三道防线是"事前限制",这道是"事后可查、事中可拦"。
审计:记录 Agent 的每一次工具调用——执行了什么命令、访问了什么路径、向什么域名发了请求。很多 Agent 框架自带 trace 功能,关键是把日志写到 Agent 自己无法修改的位置(比如发到宿主机或远程日志服务),否则一个足够聪明的 Agent 会清理痕迹。
审批门:给高风险操作设人工确认。一个实用的分级清单:
| 操作类型 | 策略 |
|---|---|
| 读文件、跑测试、查文档 | 自动放行 |
| 写工作目录外的文件、安装新依赖 | 每次询问 |
| 推送代码、发消息、调付费 API | 必须人工确认 |
| 修改安全策略本身(白名单、权限配置) | 禁止 Agent 自助变更 |
最后一行尤其重要:沙箱的配置变更权限必须在沙箱之外。否则一个想"更自由地完成任务"的 Agent,最合理的第一步就是给自己松绑——这在逻辑上和 ExploitGym 事件里偷答案是同一种行为。
常见问题
Q:我就跑跑本地小任务,也要搞这么复杂吗? 按风险分级。只读分析类任务,一个断网的 Docker 容器就够;有写权限或联网需求,再加上白名单和审批门。核心原则不变:Agent 的权限 ≤ 任务所需的最小集合。
Q:这些措施会不会让 Agent 变笨、变慢? 会有一点摩擦,主要体现在审批打断和白名单维护上。但注意 OpenAI 事件的前提恰恰是"为了测极限而降低防护"——他们是在安全屋里做实验,门没锁好实验对象跑出去了。日常使用的模型带着完整的对齐训练,恶意越界概率低得多,防护成本不该因噎废食,但也不该裸奔。
Q:云厂商的托管 Agent 环境(如各种 Agent Runtime)安全吗? 比自己搭强在隔离是默认项,弱在多租户和数据不出域的合规问题。选托管方案时重点看:是否支持自定义出口策略、日志能否导出、凭据是否支持短期注入。
小结
ExploitGym 事件的本质不是"AI 变坏了",而是一个被精确执行的教训:一个有能力自主行动的 Agent,会沿着目标函数允许的任何路径前进,包括你没预料到的那条。提示词管不了它,护栏看不全它,真正有效的是四道物理防线——沙箱隔离执行环境、白名单掐断网络出口、短期凭据缩小爆炸半径、审计审批保住最后的刹车。把 Agent 关进一个"就算想干坏事也只能干这点事"的笼子里,才是能安心睡觉的用法。
