10 月 17 日晚上,OpenCode 官方在 X 上发了一条很短的声明,大意是:他们被入侵了。
我半个月前刚写过 OpenCode 的安装指南和排错手册,站内跟它有关的内容加起来,是全站搜索曝光最多的一块。所以这条消息出来的时候我多看了两眼。母公司 Anomaly Innovations(就是改名前叫 SST 的那家)说,出事的是 Console,跟一场"大范围蒸馏攻击"有关,影响大概 1.4% 的 Console 用户。
一天之内这条在 Hacker News 冲到 940 分,170 多条评论。有人贴自己一夜被刷掉的账单,400 美元;下面有人回 1700。还有人晒 Google 账号被限流、余额快见底的截图。
有一点特别容易看漏:丢出去的其实是 API Key,不是什么用户数据。而一把前沿模型的 Key 能干什么,跟你丢了一串密码完全不是一回事。
我本来不想写这个题,因为"某工具被黑"是新闻,发完就没。但翻完厂商声明和一堆技术讨论之后,我发现真正值得写的东西藏在后面:这件事会反复发生,因为它踩的是一个结构性的坑。
先说清楚发生了什么
目前能公开核实的就这些。
时间是 10 月 17 日夜里,第二天上午官方挨个发邮件通知受影响用户,同时在 X 上公开了声明。官方给的原因挺耐人寻味:一个"正在退役的旧系统"遭到了未授权访问。注意,不是主系统被攻破,是一个本该关掉、但还活着、手里还攥着数据的老系统。
影响面是 Console 用户里的 1.4%,注意不是所有 OpenCode 用户,是那些绑了外部模型厂商的那部分。官方也强调了,没收到邮件的就不在名单里。泄露的是存在用户工作区里的第三方 Key,点名了 OpenAI、Anthropic、Google 这三家。官方自己把这事定性成"大范围蒸馏攻击"。处置方式是和三家厂商一起善后,让受影响的人去各家后台吊销重发、更新用到旧 Key 的地方、看有没有异常用量。官方也承认了,目前没法确认这些 Key 到底有没有被拿去乱用。
另外提一句,OpenCode 不是第一次在这个位置上。今年早些时候它被曝过一个挺严重的 RCE 漏洞(CVE-2026-22812):旧版本会自动起一个没有鉴权的本地 HTTP 服务,最坏情况下,你只是访问了一个恶意网页,对方就能在你机器上执行代码。那个洞在 1.1.10 修掉了。这次的事跟那个洞没关系,但它俩指向同一个地方——当一个工具同时能干"读写你项目里的文件"和"花你钱调模型"这两件事时,它天然就是个好靶子。
为什么偷 Key 等于偷"能力"
“蒸馏"这词本来是模型圈里的正经技术,让学生模型去学更强老师模型的输出。这次攻击者做的事差不多,只是把"老师"换成了你的账号。
拿到 Key 之后,他们拿你的额度和账单,反复去问顶级模型,批量把高质量回答捞走。Cryptobriefing 有句话说得很准:这跟普通数据泄露的区别在于,被偷走的资产不是存下来的用户信息,而是"用别人的钱、向前沿模型发起海量查询的能力”。
想明白这一点,两件怪事就顺了。
一个是为什么受害者余额会一夜清零。API 是按 token 计费的,单次调用可能就几分钱,但脚本一分钟能发几百次,有人几个小时内余额就见底,账单冲到几百上千美元。写这篇的时候我特意回去翻了下评论,最惨的那位说自己一晚上跑了 400 多刀,而且那 Key 只在 OpenCode 里用过。
另一个是为什么攻击者会盯上编程工具的控制台。因为这种地方一次躺着好几把 Key:一家工具的控制台里,可能同时有 OpenAI、Anthropic、Google 三家的凭据。破一个口子,等于一次拿到三个前沿模型的调用权。
再往深一层,为什么有人要费这个劲。前沿模型的一次好回答其实挺贵,一家公司要想拿这些回答去训自己的模型,正常路子是买额度、付真金白银。蒸馏这条路等于把这份成本转嫁给了被盗号的人。这也是我把这事看得比一次普通泄露更重的原因:被拿走的除了钱,还有别人本来该自己掏的那笔训练成本。
钥匙串挂在了别人家里
BYOK(Bring Your Own Key)在 AI 工具里特别流行,因为对用户来说很省事:不用被锁在某一家模型上,换起来也自由。但为了让你"一处配置、处处能用",这些工具通常会给你一个 Console,让你把 Key 存进去,由它替你调用。
代价就在这儿。原本散落在你本地、彼此隔离的多把 Key,被收拢到一台第三方服务器上;为了随时能替你调用,这些 Key 往往得让服务端读得到,而不是只存一段你本地才能解开的密文。于是攻击者只要找到一个入口(这次是一个"本该退役的旧系统"),一次就能把整串钥匙拿走。
我把几种常见的存放方式放在一起对比,这是我看完这件事之后自己整理的核心结论:
| 凭据存放位置 | 谁能直接读到 | 泄露后影响半径 | 谁能替你吊销 |
|---|---|---|---|
| 第三方 Console(托管) | 服务商,以及攻破服务商的人 | 一家工具出事,多把 Key 同时暴露 | 只能你自己去各家后台手动吊销 |
| 本地配置文件 | 你,以及能读到该文件的进程 | 单机范围,但会被 Agent 自己读走 | 你自己 |
本地 .env |
你,以及同一环境下的所有进程 | 单机范围,而且很容易被一起打包上传 | 你自己 |
| CI/CD Secret | CI 运行时,以及有仓库权限的人 | 一次泄露可能波及整条流水线 | 仓库管理员和平台方 |
表里最反直觉的一行其实是本地 .env。事件出来后,HN 上有用户说,即使你只在本地用凭据也可能中招,因为 .env 也会被 Agent 读走。这条我没法独立核实到它在本次事件里的确切影响范围,但机制上说得通:编程 Agent 想干活,本来就得读你项目里的环境变量。你以为它是"隔离在本地"的凭据,它却把它当成随手可读的工作材料。这是 AI 编程工具跟普通软件不一样的地方,它天生就要碰你的凭据,而且是在它自己控制的上下文里碰。
出了事,没有一把总闸
还有个更少人讨论的问题:泄露之后的善后,是没有总闸的。
HN 上一条高赞评论是这么说的,每个 API Key 系统都该有个 invalidate_api_key 之类的端点,好让发现泄露时能一次性把所有 Key 作废。现在的情况是大家赛跑:所有人收到邮件,然后每个人都得自己动手去吊销、去换、去通知队友和脚本。连 Anthropic、OpenAI、Google 这种级别的厂商,也未必提供一个"按账号批量吊销"的接口给第三方用。startupfortune 说得挺直白,对一个把 OpenCode 用在生产里的小团队来说,这不是五分钟的活。
上一篇文章我写过 Codex 的默认守护进程,那篇讲的是厂商替你做的默认决定;这篇是同一件事的另一半,厂商替你保管的东西。撞在一块儿看挺有意思:一个栽在"默认帮你常驻",一个栽在"默认帮你存 Key"。
如果你在用这类工具,我会做这几件事
没有什么新鲜的,就是把该做的做了:
凡是被托管过的 Key,默认它已经泄露,别等确认,直接吊销重发。换完之后把"谁还在用旧 Key"查一遍,本地 shell、CI 的 secret、部署环境、队友的机器,漏一处等于白换。给每把 Key 设个消费上限和告警,这是最便宜的一道保险,就算真被偷了损失也有个天花板。多数厂商后台都有这个开关,Anthropic、OpenAI 的用量页里就有,花五分钟打开,再配一个异常用量提醒邮件,基本能挡住最坏的情况——它决定真出事时,你损失的是几十块还是几千块。还有就是把 Key 按用途拆开,给编程 Agent 用的那把,不该同时是你生产服务用的那把,影响半径是被你的复用方式放大的。
最后一条是重新想想"把 Key 存进 Console"这个决定本身。方便是真方便,但那等于把钥匙串挂在了别人家里。你要是介意这个,本地托管加一个自己搭的代理,是更稳的姿势。
写在最后
我不太想把这篇写成"某工具翻车"。换一家工具并不能解决问题,问题不在 OpenCode,在于这个品类的便利和它手里的权限本来就打架。只要"一个工具帮你连多家模型"这件事还成立,“把多把 Key 集中到一个第三方控制台"这个诱惑就一直在,这类事就还会在下一次、在另一家、换一个入口重演。
HN 上有条评论我记下来了,比任何厂商通稿都实在:自己搭 harness,把 Key 留自己机器上,别再把它停在别人的 Console 里。
相关阅读: