密钥的家太多了
Wiz 统计,10 月至少有九个 AI 开发平台披露遭到入侵,多数可追溯到凭据访问,攻击者盯上的是保存着 AI 密钥的已存储环境变量。最新的一家 Northflank 在 10 月 30 日告诉客户,要假定每个环境变量都已被解密,用户也报告自己的 AI 密钥在几小时内就被人使用。在 Bromure Agentic Coding 里,代理写代码用的密钥只放在你 Mac 上的一个地方,代理无法把它复制到任何平台,轮换只需粘贴一次。
你把 AI 密钥粘贴进哪个平台,那个平台就留着一份副本。10 月,攻击者在九个平台上冲着这些副本而来,Wiz 看到被盗的密钥在 30 分钟内就被拿去测试。
10 月 30 日 11:43 UTC,Wiz 通知 Northflank 遭到入侵。Northflank 是一个用于部署应用、数据库和 AI 工作负载的云平台。大约两小时后,Northflank 的状态页告诉所有客户:“Assume all environment variables have been decrypted. Disable/rotate all keys.”(请假定所有环境变量都已被解密,停用或轮换所有密钥。)15:12 它补充道:“Multiple users are confirming that their AI keys have been used.”(多位用户确认他们的 AI 密钥已被使用。)当天最后一次更新在 23:38:“Users have reported unauthorised use of AI API keys supplied to the Northflank platform.”(用户报告,提供给 Northflank 平台的 AI API 密钥遭到未经授权的使用。)BleepingComputer 报道称,Northflank 既没有说明攻击者如何进入,也没有说有多少客户受到影响。
Northflank 并不是第一个。同一天,Wiz 研究员 Benjamin Read 和 Rami McCarthy 发布了 Black October for AI Developer Platforms,统计出本月至少有九个 AI 开发平台披露了安全事件。“换作其他任何一个月,这都会是头号安全新闻。”他们写道。
一个月,九个平台
Wiz 的清单,按时间排列:
| 日期 | 平台 | 披露内容 |
|---|---|---|
| 10/6 | Fireworks AI | 凭据访问;有“代理蜂群”攻击的迹象 |
| 10/9 | Andromeda | 属于一场“全行业攻击” |
| 10/14 | Zeabur | 凭据访问;公司将停止运营 |
| 10/15 | Lightning AI | 凭据访问 |
| 10/16–17 | OpenCode | 一套“遗留系统”;存储的服务商密钥泄露 |
| 10/20 | Railway | “我们的构建基础设施遭到权限提升” |
| 10/23 | Warp | 第三方供应商;代理追踪记录被取走 |
| 10/28 | CommandCode | 归因于蒸馏 |
| 10/30 | Northflank | 环境变量视为已被解密 |
Wiz 没有找到九起事件共同的单一漏洞或依赖。它们共有的是目标。多数事件可追溯到凭据访问,攻击者专找已存储的环境变量,“尤其是那些能访问 AI 的”。OpenCode 和 CommandCode 归咎于蒸馏,也就是用盗来的前沿模型访问权去训练更便宜的模型。其余的需求,Wiz 则联系到它称为 LLMJacking 的转售市场:被盗的密钥被当作打折的模型访问权出售。
三十分钟内测试,按百万次转售
Wiz 还追踪了两组被盗、用于 Amazon Bedrock 的企业凭据后来的去向。Wiz 无法把任何一起案例与特定平台的入侵联系起来,但这个模式说明了 AI 密钥为何值得猎取:
- 在通报的凭据访问发生后 30 分钟内,一次来自住宅 IP 的
InvokeModel调用测试了这些密钥。它请求 Claude Fable 5.1,失败后改用 Opus 5.5,成功了。 - 接着一个小型 Go 客户端每天检查密钥 14 到 120 次,确认它们仍然可用。
- 一个
boto3脚本枚举了 Bedrock 和 EC2 的配额。同一个脚本,连版本字符串都一样,出现在两起案例中。 - 然后才是大批量流量。案例 A 在约 30 小时内发出约 80 万次 Bedrock 调用,约 90% 成功。案例 B 在约 13 小时内发出约 170 万次调用,超过一百万次成功。
Wiz 估计,按标价计算,这两起案例“很可能累计产生了超过 10 万美元的用量”。token 模式看起来像转售的编码代理流量:使用提示缓存,一个转售商背后有许多终端用户。Wiz 把接触过这些密钥的基础设施与 LLM 转售网站联系起来,其中一个接受 USDT 付款。
被盗的 AI 密钥就流向这个市场:一群人用别人的账单跑编码代理。
一把密钥如何落到九个地方
一位开发者拿到一把 Anthropic 密钥,开始使用。它先进了编码代理,再进了预览部署好让应用的 AI 功能能用,再进了跑评估的 CI 任务,再进了一个 notebook 服务来试微调。每次粘贴只要三十秒,就能让某样东西跑起来。你再也不会回头去看其中任何一处。
编码代理让这件事变得更快。让它“把这个部署到 Northflank”或“配置 Railway 服务”,它就会做开发者会做的事:从环境中读取 ANTHROPIC_API_KEY,再把它作为服务变量交给平台的 CLI。部署成功了。密钥现在又多住进了一个平台,就在数据库密码旁边,而且没有任何人亲手输入过它。
接着某个平台被入侵,建议每次都一样。Northflank 的是“Revoke existing credentials with their issuing providers, generate replacements”(向签发方吊销现有凭据,生成替代凭据)。要做到这一点,你得先记得那把密钥去过的每一个地方。
同一个月的 Bromure Agentic Coding
Bromure Agentic Coding 在你 Mac 上的 Ubuntu 虚拟机里运行 Claude Code、Codex、Grok、Kimi 和 omp,每台机器一个虚拟机。代理、它的代码仓库以及它执行的每条命令都在虚拟机里。真正的凭据,以及虚拟机所有流量都要经过的代理服务器,则留在 Mac 上。
密钥只住在一个地方
模型密钥只在 Preferences › Models 输入一次。Bromure 把它们存放在 models.enc 中,用 AES-GCM 加密,主密钥放在 Mac 的 Data Protection Keychain 里,并关闭 iCloud 同步。这个应用不会把任何凭据、token 存储或密钥材料上传、同步或备份到任何地方。Bromure 不运营任何存储服务商密钥的控制台,所以攻击者在我们这边找不到可以入侵的东西。
在每个虚拟机里,ANTHROPIC_API_KEY 存的是一个以 sk-ant-api03-brm- 开头的替身。Claude Code 接受它,因为格式正确。代理调用 api.anthropic.com 时,请求经由你 Mac 上的代理服务器离开虚拟机,代理服务器换上真正的密钥后再转发。代理服务器只为服务商自己的主机加上密钥,其他一律不加:Anthropic 密钥对应 anthropic.com,OpenAI 密钥对应 openai.com,依此类推。
如果你改用 Claude、ChatGPT、Grok 或 Kimi 订阅登录,OAuth token 留在 Mac 上,也由 Mac 负责刷新。虚拟机从不持有 refresh token。
代理无法把它扩散出去
现在重演那次部署。代理运行平台的 CLI,用环境中的值在服务上设置 ANTHROPIC_API_KEY。那个值是替身,而携带它的请求发往平台的 API。
Bromure 的代理服务器会检查每个出站请求的请求头和请求体,找出被发往非其签发对象主机的替身。一个出现在部署平台 API 请求中的 Anthropic 密钥替身就是其中之一。代理服务器在任何一个字节到达平台之前,就以 HTTP 451 拦下请求、暂停虚拟机,并显示 This environment may have been compromised,列出凭据名称、它所属的主机,以及它被发往的主机。
我们打造这个警报是为了对付窃取密钥的恶意软件,而它对一个想帮忙的代理同样会触发。你写代码用的密钥不会在你不知情的情况下被复制到部署平台。如果这份副本正是你想要的,Allow 会在本次会话剩余时间里把它发往该主机。更好的做法是为生产环境服务另外签发一把仅限生产环境使用的密钥,让代理写代码用的密钥留在你的 Mac 上。
代理也会把机密往反方向拉。railway variables 或平台的 env pull 可能会把生产环境的 .env 连同真实值一起放进代码仓库。在机器的 Guardrails 中开启 Only allow credentials Bromure injects,任何携带非 Bromure 注入之凭据的请求都会被拦下,并触发同样的警报。代理从平台下载的真实密钥就只能闲置在虚拟机里。
没有密钥可偷的 Bedrock
Wiz 追踪的两起下游案例,都是用长期有效的企业凭据在 Amazon Bedrock 上运行。在 Bromure 里,任何代理都能在 Bedrock 上运行,Claude Code 原生支持,其他则通过 Bedrock 的 OpenAI 兼容 API,而且都完全不需要 Bedrock 密钥。把 Bedrock API key 字段留空,Mac 就会用该机器的 AWS 凭据为每个请求签名。
这些凭据可以是临时的。在机器的 AWS 凭据中选择 SSO / Identity Center,Mac 就会从你的 SSO 缓存获取短期角色凭据,并在到期前约五分钟刷新。虚拟机拿到的是一把假的秘密密钥,它生成的签名会被 AWS 拒绝;Mac 会去掉这些签名并重新签名。任何地方都没有环境变量存放长期的 Bedrock 凭据,等着被人解密。
轮换只需粘贴一次
当平台要求你轮换时,你的代理所用的密钥只是一个字段。在 Preferences › Models 粘贴新密钥,Bromure 会在你停止输入约一秒半后,把它应用到每一台使用它的运行中机器。凭据有变化的代理会带着恢复参数重新启动,所以对话会接着进行。虚拟机不会重启,里面也没有任何东西需要修改,因为里面从来没有东西持有旧密钥。
如果你的密钥放在 1Password,机器的其他 API 密钥可以用 op:// 引用代替实际值。Bromure 在 Mac 上解析它们,并每两分钟重新解析一次,所以在 1Password 轮换条目后,几分钟内就会传到运行中的机器,无需重启。
你自己的每次使用记录
Northflank 的另一条建议,是检查服务商的用量和账单记录,看有没有不是你发起的活动。在 Bromure 里,每次替换都是你 Mac 上 Security Timeline 中 Credential brokering 下的一行,附有打码的密钥预览和主机,例如 sk-a…f9q3 → api.anthropic.com。AWS 签名,包括 Bedrock,会以 Credential used 行出现,附有打码的访问密钥。当服务商的仪表板出现激增时,你能看出哪些调用来自你自己的机器。
在注册到 Bromure Enterprise Manager 的 Mac 上,同样的替换会以 credential.token_swap 事件流式发送到你的组织,只带预览,绝不带密钥本身。需要回答“我们有没有密钥在别处被使用?”的管理员,手里就有整个机群合法使用那一侧的记录。
一份副本,在 Mac 上
模型密钥存放在 models.enc,以 Keychain 密钥加密,从不同步或上传。没有任何厂商控制台持有它们。
虚拟机里是替身
代理的 ANTHROPIC_API_KEY 是替身。真正的密钥在 Mac 上添加,只给服务商自己的主机。
不会意外复制
发往部署平台的替身会被 451 拦下,虚拟机暂停,警报会指出目的地。
严格凭据
开启严格模式后,代理从平台 env 文件拉下来的真实密钥,一使用就会被拦下。
用 SSO 跑 Bedrock
Mac 用短期的 Identity Center 凭据为 Bedrock 调用签名。没有长期密钥可存放或窃取。
粘贴一次即轮换
在 Preferences › Models 输入的新密钥,几秒内就会传到每个运行中的代理。虚拟机不会重启。
数一数你的副本
Wiz 还不知道九起事件背后是否是同一个团伙,而多数平台也尚未公布根本原因。每个存储你 AI 密钥的平台都可能丢失它,而 10 月证明了,窃贼如今已有买家在等着。
代理写代码用的密钥,正是你最不希望出现在那份清单上的那一把。它能用你最好的模型和最高的额度,而且你的代理整天都在用。在 Bromure Agentic Coding 里,它留在你的 Mac 上。代理拿到的是替身,其他任何平台都用不了。
关于 OpenCode 控制台遭入侵,也就是 10 月九起事件之一,请阅读密钥就放在他们的控制台里。关于 Warp 被盗的代理追踪记录,请阅读代理的日志存在他们的云端。