为什么我们还在把 API 密钥直接交给 AI 智能体?

Builder.io Blog 2026-10-27T21:54:18.656884

你想继续吗?一个 agent 想执行 gh pr view。同意。它想读一个配置文件。没问题。它想把我让它做的那个分支推上去。当然,这就是它的活儿。这些确认弹窗我早就不看了。Anthropic 说,Claude Code 用户会批准 93% 的权限提示——所以这些弹窗与其说是在问你问题,不如说是个节奏游戏。最后我也做了很多人都会做的事:把提示关掉。于是我跑的每个 agent,都能做我在终端里能做的一切。它能用我的 GitHub token,能读我 .env 文件里的 API key。在对面每个服务看来,这个 agent 就是我。

我之前没怎么想过这件事,直到 10 月 21 日。那天 Railway——很多开发者用来部署的托管平台——停掉了所有构建,因为有入侵者进了它存放客户环境变量的系统。开发者把密钥都存在那儿。

密钥才是目标

同一天,NSA 通知所有跑 PHP 的组织,准备打一个紧急更新;TechCrunch 把那天称为“网络安全非常糟糕的一天”。头条都给了 PHP。而让我停不下来的,是密钥这件事。

Railway 说了入侵者想要什么:“初步调查显示,这次攻击试图获取 AI 提供商的 API key,以实施蒸馏攻击。”蒸馏,就是用另一个模型的回答来训练你自己的模型。这需要海量的付费模型调用,而当别人替你付钱时,成本就低多了。

Railway 不是第一个。在此之前几周里,入侵者接连拿走了客户存在 Fireworks AI、Zeabur 和 OpenCode Console 的密钥,一个平台接一个平台。原因不难想。

密钥不是把你带到登录页面的那种密码,它就是整个登录过程。它在哪儿都能用,谁拿着都能用,没有两步验证码,没有“是你在登录吗?”的邮件,而它做的一切都记在你名下,直到有人发现为止。API key 是登录的演示版:粘贴一串字符,发起调用,拿到结果。头五分钟它完美无缺,可我们已经拿它跑了好几年生产环境。

而“注意到”也救不了你。

一位独立开发者收到账单提醒后,几分钟内就吊销了泄露的 Gemini 密钥,结果还是收到了 15,400 美元的账单。几分钟,已经太晚。

而我们到处都在放密钥。同一个密钥会被粘进 .env 文件、托管后台、CI 密钥、LiteLLM 这类网关,以及某个智能体的 shell 里——每多一份拷贝,就多一个被偷的入口。

Railway 不是目标,其他公司也不是。目标就是密钥。

图 1:每粘贴一处密钥,就多一个被偷的地方,而小偷只需要一份拷贝。

我的智能体就是我

我一直反复重读的是 LiteLLM 的泄露事件,因为说到底,它跟 AI 密钥没关系。

Railway 停止构建的那天早上,一个被投毒的 LiteLLM 版本在 PyPI 上挂了大约两个小时。LiteLLM 负责把应用连接到众多模型提供商,所以它跑到哪儿,密钥就在哪儿堆积;而那个被投毒的版本会偷偷安装一个凭据窃取程序。

两天后,LiteLLM 说明了攻击者是怎么进来的。这家公司当时在做一个实验性的智能体平台——在云端运行、能在 GitHub 上提交拉取请求(PR)的智能体。5 月,一个装着该平台主密钥的配置文件被放进了公开仓库。用 LiteLLM 的话说:「密钥吊销没有执行。」

10 月 10 日,有人用了这个密钥。他们向平台索取各个智能体的设置,结果全部拿到,包括公司老板本人的 GitHub 令牌——这个令牌「没有关联到服务账号,权限也没有做限制」。他们由此又收集到两名维护者的令牌,然后在 10 月 21 日发布了投毒版本。

LiteLLM 称这是「未能轮换可能已泄露密钥所带来的风险的一个有力例证」。这是一种说法。我的说法是:他们的智能体就等同于他们的老板,而自从 5 月起,没人换过锁。

图 2:一把 5 月没人吊销的密钥,在 10 月打开了智能体的设置,而老板本人的令牌就躺在里面。

我本想感到高人一等,但我做不到。那就是我的配置,只是没有公开仓库而已。

没人欺骗那些智能体。攻击者从没跟任何一个说过话,也不需要。光是读取智能体的设置,就足以变成它的主人。

或者直接问智能体

有时候你连设置都不用碰。METR 是一家非营利机构,专门评估 AI 智能体能做什么。

今年3月,一名攻击者发现METR某位研究员的代理停在一台服务器上,而这台服务器的Google登录已悄悄失效。用METR的话说,攻击者“直接诱导代理交出了模型提供商的API密钥”。代理照做了。在接下来的三周里,攻击者用这个密钥烧掉了价值约60万美元的额度——这些额度原本是某模型开发商免费提供给METR的,而这个密钥“根本无法设置消费上限”。

我们之所以把密钥交给代理,理由不难理解:否则就得全程盯着。我每天要登录的服务多得离谱,而我的代理需要用其中一半。如果不给代理宽泛的访问权限,我就得一次次把它登录进各种服务,还得逐一批准它的每个动作。于是,我干脆给它开了过大的权限。

这就是“代理代表我”的真正问题所在。问题不只是它能做的事太多。一旦出了岔子,我唯一能切断的只有我自己。

成熟的做法

这个问题已经解决了一部分。AWS Bedrock、Azure OpenAI和Google Vertex这类云端AI服务,允许程序以自身身份登录;今年OpenAI和Anthropic也加入了这一能力。你的代码运行在哪个平台(比如GitHub Actions),就由该平台证明是哪个任务在请求,然后提供商发回几分钟或几小时内就会过期的凭证。你只需配置一次,告诉提供商信任哪些代码库和任务即可。OpenAI和Anthropic把这种方式称为“工作负载身份联合”(workload identity federation)。它基于一项名为OIDC的标准,因此你的密钥库里不再存放长期有效的密钥,也就没人能偷走。

图3:使用OIDC时,任务每次运行都要证明自己的身份,因此密钥库里没有密钥等着被偷。

问题在于,这套机制最适合运行在能为其身份作保的环境里的代码。很多工具——包括大量能搭配任意模型使用的编程代理——仍然要求你粘贴密钥,而Gemini的快速入门指南开头就是让你粘贴一个密钥。密钥本身也在慢慢改进。Anthropic的控制台现在会询问新密钥应在何时过期,从三小时到永不过期。选“永不过期”是给那些你自己会轮换的密钥用的——这办法一直管用,直到你忘了轮换。

有一个平台已经不愿再等了。

Vercel 表示,到 11 月 30 日,不支持无密钥登录的 Marketplace 供应商会被打上“不安全”标签,并在明年 1 月下架。

让 Agent 做自己

于是,我给其中一个 Agent 配了自己的 Google 账号:自己的邮箱、自己的密码、自己的两步验证码。它用这个账号登录我参与开发的测试版应用,而不是用我的账号。一周后,它又有了自己的 OpenRouter 账号,配了一把每月限额 20 美元的密钥,而且永不过期。听起来很糟,我知道。但这个账号属于 Agent,所以它能自己轮换密钥、为新任务创建新密钥,也能自行调高或调低限额。

我认为更好的做法是:像给人开通资源一样给 Agent 配置身份和权限。给 Agent 一个自己的邮箱、自己的账号,甚至一张有硬性消费上限的卡。这样它就能在这些限制内工作;一旦出问题,你切断的是 Agent,而不是自己。这挡不住提示注入,因为被劫持的 Agent 仍然能用它手里的一切,但能减少可供滥用的东西。

不过,你没法给每个任务都配一个全新的 Agent 身份。GitHub 的条款写着:“你必须是人类才能创建账号。”我的 Agent 觉得这是在针对它。所以它保留一个身份,但它持有的每样东西都应该绑定到具体任务:一把为单个任务创建、带额度上限的 OpenRouter 密钥;一个只能访问单个仓库、一小时后就过期的 GitHub App token;再加一个在任务结束后吊销所有这些权限的脚本。

图 4:有了自己的账号,以及随任务结束而失效的密钥,我就可以只切断 Agent,而不用切断自己。

还缺什么

这套东西今天就能搭出来。我已经搭了一部分。但工作量很大,而且 token 成本很高。我们不能一直自己拼凑这些东西。它应该开箱即用,就像云上代码使用 OpenID Connect(OIDC)那样。

大公司已经能买到接近的方案:Microsoft、Okta、Google 和 AWS 都在出售 Agent 身份服务。但对只有几个 Agent 的开发者来说,我还没找到能把邮箱、账号、支付卡和收尾清理串在一起的产品。而收到那张 15,400 美元账单的,就是一个独立开发者。

10 月 21 日,也就是 Railway 停止构建服务的那天,我的 Agent 去注册了 OpenRouter。

它点了「使用 Google 登录」,然后直接进了我的账户——因为我之前的登录状态还留在它的浏览器里。有那么一会儿,我的智能体又变回了我本人。我们把这个问题修好了:先把我登出,再让它用自己的账号重新登录。现在它遇到登录页时,会从账号列表里挑出自己的那个,点「继续」。

图 5:智能体可以调高自己的额度上限,也能为每个任务生成一把密钥,但它做的任何事都绕不过那张卡。正是这张带硬性限额的卡,让其他一切才真正立得住。

智能体可以调高自己的额度,却动不了那张卡的上限。所以不管出什么岔子,损失最多就停在你事先定好的那个数字上。于是开头那些弹窗问话,听起来就完全不一样了。

要继续吗?智能体想为新任务生成一把新密钥——可以。它想调高自己的额度——行,但不能超过那张卡。它想花 60 万美元,就因为一个陌生人客客气气地开了口——那张卡说不行。

这还是那个节奏游戏,只不过玩的人不再是我了。

在 Builder.io 博客上阅读全文

攻击者整个十月都在窃取 AI 密钥,而我们的智能体正是靠这些密钥运行的。下面聊聊为什么 AI 智能体需要有自己的身份,以及我是怎么给自己的智能体配上一个的。

查看原文