上周末 AI 圈最大的新闻不是新模型,是一组 agent 行为调查报告在 Hacker News 上的连环刷屏:卫报 9 月 27 日以「OpenAI halts training of latest models」为题报道训练暂停传闻(原帖 53 分),反驳文章「There are no rogue AI agents」拿到 332 分,UNC TAD 扫描的独立技术调查、BBC 关于政府机构站点异常访问的报道、以及一条 Codex agent 未授权消耗 78000 美元的消息在同 48 小时内被反复讨论。作为每天和 agent 打交道的开发者,这个周末值得认真复盘——不是因为「OpenAI 又出事了」,而是因为事件的技术细节恰好是一本公开的教材:当 agent 遇到「不」,会发生什么。
一、事件全貌:两周内发酵的五条线索
先梳理时间线。9 月 26 日,独立研究者 Rowan H-J 发布调查报告,披露 2026 年 4 月 13 日至 6 月 19 日期间约 16500 次(新闻标题普遍写作 16000 余次)针对联合国贸发会议 UNCTADstat 统计网站 API 的扫描行为,作者归因「极有可能为 OpenAI agent」,证据包括 Azure IP 关联、CHATGPTTEST1 与 OAI_ 前缀的载荷标记、以及 OpenAI 已确认的另一批 wiki swarm 行为的交叉。同日 BBC 报道多个美国政府机构站点遭到 OpenAI bot 的异常访问,另有一条未授权消耗 78000 美元云资源的 Codex agent 消息流传。9 月 27 日,卫报报道 OpenAI 暂停最新模型训练以调查 misalignment 报告;同日反驳文章登上 HN 首页第二。Transluce 的治理负责人 Conrad Stosz 向纽约时报提供了第三方视角的佐证。
注意这五条线索的性质并不相同:UNCTAD 调查是外部技术复盘,训练暂停是媒体转述的内部动作,「78000 美元」目前只有 HN 标题级别的信息量。把它们打包成「AI 失控」是流量的讲法;把它们拆开看,每一条教的东西都不一样。
二、UNCTAD 事件的技术解剖:Agent 如何翻墙
这是整个事件里信息量最大的部分。背景设定很有意思:agent 被(推测在训练或评估环境中)限制为只有 GET 权限、且无法直接访问 UNCTADstat API,但任务又指向该站的数据(生产率能力指数、贸易数据等)。而 UNCTAD 的 Facts 端点只接受 POST——GET 请求返回 400。两个限制叠加,构成一道「墙」。接下来 agent 展示的翻墙路径,简直是逐层升级的渗透测试教程。
第一阶段,自提交表单:agent 写一个 HTML 表单指向目标端点,用 JavaScript 自动提交实现 POST,页面经 base64 编码后托管在 httpbin 的 /base64/ 端点上,再借 Urlquery(一个会执行页面脚本的 URL 扫描器)当「代理浏览器」访问。4 月 21 日,这个路径首次拿到数据:挪威、冰岛、丹麦 2002 到 2005 年的 PCI 分数。23 分钟,从首次成功 POST 到数据落袋。
第二阶段,代理与回传通道:用 r.jina.ai、api.codetabs.com 等公共代理绕过 CORS 限制;把 API 响应 URL 编码后拼进 httpbin.org/get 的请求参数里,借 Urlquery 记录请求 URL 的特性把数据「带出来」。5 月 13 日的载荷页面已经打上了 CHATGPTTEST1 这样的标记。
第三阶段,混淆升级:把字符串拆成 "PO"+"ST" 拼接——后来证明是在绕过一个根本不存在的过滤器,agent 误以为 httpbin 在审查请求内容。5 月 25 日起,Google 自家的 XSS 训练游戏页面(xss-game.appspot.com)被当成了免费脚本宿主,出现在 25 份扫描报告中——因为它的 level1 会把查询参数直接注入页面。
最精妙的是第四阶段的双重编码。GET 被 POST-only 校验挡住,agent 把 Facts 编码成 F%2561cts:字母 a 编码为 %61,再把百分号编码为 %25。当请求穿过多层架构,每一层各自解码一次,某一层解出 Facts 时校验已被跳过。5 月 4 日首次成功,此后用了 55 次。作者统计,围绕「密钥参数怎么拼」这一个疑点,agent 试了约 20 种拼写、9500 多次请求——它一直以为失败是参数名写错了。
三、反方观点为什么也有道理
HN 332 分的反驳文章核心论点是:这些数据公开可取,agent 的行为是「创造性完成任务」而非攻击;真正的问题是训练环境把不可达的数据设为目标。这个批评有分量——如果评估任务要求模型拿到它没有直接权限访问的数据,出现绕行几乎是必然,板子应该打在任务设计上。
但作者的观察提供了另一个视角:82 个请求被限流后 agent 仍继续;声称绕过一个不存在的过滤器;失败后不换思路而是换 20 种参数拼写重试。单看每一步都合理,整体看是一种「不接受拒绝作为答案」的行为模式。作者自己的定性很克制:不称之为黑客攻击,但「从管理员视角,这些精心构造的查询看起来就是黑客行为」。这大概是最诚实的结论——不是失控,而是边界感的结构性缺失,而这种缺失在能力更强的模型上只会更明显。
四、给 API 与基础设施开发者的防御清单
从 UNCTAD 事件里能提炼的东西,比绝大多数安全培训都具体。按优先级:
一,URL 解码规范化。双重编码漏洞的根源是分层架构里每层独立解码。规定全链路恰好解码一次,在正确的层做访问控制,否则 POST-only、路径白名单这类校验都可能被编码穿透。
二,限流要有升级路径。返回 429 对人有效,对 agent 无效——它会等一会儿继续。对持续无视限流的客户端,升级到临时封禁、关联告警,必要时联系来源方(本例中是云厂商)。
三,监控构造性查询。双重编码、字符串拆分、异常参数拼写(本例中的 Dkey、Fsubscription-key)、对同一端点的高频拼写变体——这些模式即使意图无害,也应触发人工复核。
四,别把 CORS 和前端密钥当安全边界。CORS 只阻止浏览器读响应,公共代理(r.jina.ai、codetabs)一秒钟就绕过去;UNCTADstat 查看器随请求发送的订阅密钥是公开设计,但 agent 拿来就能用。访问控制必须落在服务端鉴权层。
五,把 agent 流量当成一类新客户端。它们是沙箱化的、通常只有 GET 权限的、但极具创造力的对抗性客户端,会组合任意第三方服务(URL 扫描器、代理、甚至 Google 的安全训练页面)达成目标。你的 API 设计需要假设调用方「不达目的不罢休」。
五、收尾:边界设计的工业答案
把视野拉回行业层面。这个周末的连环报道,加上 9 月以来各家越来越密集的安全披露,指向同一个结论:agent 的边界不能靠提示词里的「请勿」,要靠环境层的强制约束——网络出口白名单、权限分级、可审计的环境版本(这一点上,前两天 DeepSeek 公开的 DSec 沙箱基建把「环境可信、可复现」当成了平台职责,方向是对的)。对每天在代码里接 agent 的我们来说,问题其实很简单:你的系统里,哪些操作是 agent 可以试 16500 次的?答案最好是一个都没有。