AI智能体安全:API密钥、沙箱与消费限额
AI智能体安全实战:如何保护API密钥,在Claude Code中设置权限和沙箱,配置消费限额并扫描密钥泄露。分步讲解。
本文的其他语言版本:العربيةDeutschEnglishEspañolFrançaisItaliano日本語Polski
本文内容
AI智能体安全归根结底是三件事:智能体只能看到它需要的东西,API密钥不放在智能体(或攻击者)能读到的地方,每个密钥都设有消费限额。下面是一个下午就能做完的五个步骤:权限、沙箱、整理密钥、限额,以及扫描代码仓库。
为什么AI智能体安全变得紧迫?
最近几周的例子已经足够多了。OpenCode泄露事件之后,有用户晒出了自己的密钥被他人盗用产生的账单。在针对100多家公司的AI黑客攻击中,智能体几乎无需人工参与就完成了入侵,而暴露在外的Cairn面板上躺着数百个密钥。此外,Meta Muse泄露事件表明,就连“分享对话”这样的功能也可能泄露比想象中更多的信息。
10月21日又出了一件事:据SafeDep报告,热门库LiteLLM的1.107.0版本被发布到PyPI时带有一个窃密程序和一个后门,窃密程序会收集SSH密钥、云服务凭据、CI/CD密钥以及LLM服务商的API密钥等。攻击者掌握了三名开发者的GitHub CLI登录凭据。PyPI当天就下架了该版本,1.106.2等版本是干净的。
智能体和聊天的区别在于,它会执行操作:读取文件、运行命令、访问网页。OWASP描述了两大主要风险:
- 提示词注入(Prompt injection)。 据OWASP介绍,在间接注入中,模型会接受“from external sources, such as websites or files”的指令。只需一个藏有隐藏指令的README或网页,就足以让智能体去做我们从未要求过的事。
- 过度代理(excessive agency)。 OWASP列出了三个原因:功能过多、权限过多和自主性过高。在2026年榜单的预告中,这一风险升至第三位。
OWASP还单独维护着一份智能体应用Top 10榜单,排名第一的是“Agent Goal Hijack”,即劫持智能体的目标。
两份榜单的黄金法则是一样的:只给完成任务所需的最小权限,高风险操作须经人工批准。
第1步:如何在Claude Code中设置权限?
我以Claude Code为例(从零开始的介绍见我的Claude Code教程),不过同样的思路也适用于其他智能体框架。
权限在settings.json中以allow、ask和deny规则来设置。据文档,顺序是固定的:“deny, then ask, then allow”,所以拒绝规则永远优先。我们先封锁对密钥文件的访问。下面这个例子直接取自设置参考:
{
"permissions": {
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Read(./config/credentials.json)",
"Bash(curl *)"
]
}
}
需要注意的是,deny规则有其局限,文档也直言不讳:
- 对不指明文件名就读取文件的命令(例如
grep -r pattern .)以及任意子进程无效。 Bash(curl *)是按字面匹配命令的,所以拦不住/usr/bin/curl或sh -c 'curl …'。.claudeignore文件完全不起作用,其中的条目需要移到deny下的Read规则中。
因此,规则只是第一道防线,而不是全部防护。当前权限可以用/permissions命令查看。
第二件事是工作模式。Claude Code有default、acceptEdits、plan、auto、dontAsk和bypassPermissions几种模式。关于最后一种,文档写道:“Only use this mode in isolated environments like containers or VMs”。在共用电脑上,可以把permissions.disableBypassPermissionsMode设为"disable"来彻底禁用它。
第2步:如何开启沙箱?
沙箱是由操作系统本身守护的边界,所以在deny规则管不到的地方也能起作用。据沙箱文档,它默认是关闭的。在会话中用命令开启:
/sandbox
或者在~/.claude/settings.json中把sandbox.enabled设为true。在macOS上开箱即用,在Linux和WSL2上则需要两个软件包:
sudo apt-get install bubblewrap socat
在没有WSL2的Windows上没有沙箱,命令在无隔离的情况下运行。
开启沙箱后能得到什么:
- 命令只能写入工作目录和临时文件。
- 网络流量经过本地代理,允许访问的域名列表(
network.allowedDomains)初始为空。 - 不过,它们仍能读取磁盘的大部分内容,包括
~/.ssh和~/.aws/credentials。这些路径需要我们自己通过filesystem.denyRead或credentials部分来封锁,因为文档写明:“There is no built-in credential deny list”。
文档里还有两点提醒。第一,沙箱只覆盖shell命令:Read、Edit、Write和WebFetch工具、hooks以及本地MCP服务器都在沙箱之外运行。第二,在允许列表中加入github.com这类宽泛的域名,可能为数据外泄打开通道。想要一次性隔离所有东西,应该把整个智能体放在容器或虚拟机里运行。
在OpenAI的Codex中,对应的是read-only、workspace-write和danger-full-access模式,网络默认关闭。--yolo参数(--dangerously-bypass-approvals-and-sandbox的别名)会同时关闭审批和沙箱,所以还是留给容器用吧。
第3步:API密钥该放在哪里?
最简单的规则:密钥不进代码,也不进仓库。Anthropic建议不要把密钥直接写进代码或配置文件,并把.env文件加入.gitignore。OpenAI建议通过环境变量或密钥管理器传递密钥,并定期轮换。
具体做法:
- 开发、测试和生产环境使用不同的密钥(这也是Anthropic的建议)。这样一次泄露不会让一切瘫痪。
- 给智能体用的是一个单独的密钥,有自己的限额,而不是我们的主密钥。
- 发生泄露后,立即吊销密钥,然后再去查原因。
有意思的是,GitHub自己就能拦下部分泄露。如果Claude的密钥被推送到公开仓库,GitHub会通知Anthropic,后者会自动停用该密钥。
第4步:如何设置消费限额?
限额挡不住泄露,但能在密钥落入他人之手时控制账单金额。
- Anthropic。 在Claude Console中进入Billing页面(
platform.claude.com/settings/billing),在Spend limits部分点击Adjust limit或Set limit。除默认workspace外,也可以按workspace设置限额。 - OpenAI。 在项目设置中进入Limits,设置Monthly spend limit并开启Enforce a hard limit。注意:消费提醒(“Spend alerts do not enforce a cap”)不会拦截任何东西,而限额本身生效有延迟,所以实际消费可能会略微超出。
一个好习惯是每个智能体一个项目(或workspace),各自拥有独立的密钥和限额。
第5步:如何在泄露前发现密钥?
智能体写大量代码,也很乐意提交commit,所以值得准备一个自动机制,在push之前拦下密钥。
- GitHub的推送保护(push protection)。 据文档,它会在包含密钥的推送进入仓库之前将其拦截。对用户账户而言,公开仓库默认开启;在仓库层面则默认关闭,并需要GitHub Secret Protection。
- 本地运行Gitleaks。 通过
brew install gitleaks安装,然后扫描目录或git历史(README):
gitleaks dir -v .
gitleaks git -v .
- TruffleHog还会检查找到的密钥是否仍然有效(README)。NorForge正是用这个工具确认了Cairn面板上的部分密钥仍处于有效状态:
trufflehog filesystem path/to/dir
使用MCP服务器要注意什么?
MCP服务器是以我们的权限运行的代码。Claude Code文档建议自己编写服务器,或只使用可信提供方的服务器,并指出Anthropic不会审核MCP服务器。
MCP安全最佳实践(规范的草案版本)补充了几个具体要点:
- 客户端应当显示启动本地服务器的完整命令,不做截断。规范中的攻击示例是一个看似无害的
npx,背后却藏着把~/.ssh/id_rsa发送到陌生服务器的curl。 - 本地服务器最好在权限最小化的沙箱中、通过
stdio传输方式运行。 - 服务器不得接受并非为它签发的令牌(所谓的“token passthrough”是被禁止的)。
- OAuth权限要逐步授予,不要使用
*、all或full-access这类宽泛的范围。
常见问题
Claude Code的deny规则足以保护.env文件吗?
不完全。它们能拦住内置工具和cat等可识别的命令,但拦不住grep -r或任意子进程。只有沙箱配合filesystem.denyRead才能在系统层面提供完整保护。
API密钥泄露了怎么办?
立即在服务商的控制台中吊销它,生成新密钥,在所有应用中替换,并检查账户最近的用量。详见关于OpenCode泄露事件的文章。
什么是AI智能体中的提示词注入?
就是藏在智能体所读取内容(网页、文件、邮件)中的指令。智能体可能会像执行我们的指令一样执行它们。因此,高风险操作应当需要我们的批准,而且智能体不应接触到密钥。
沙箱能在Windows上使用吗?
在Claude Code中只能通过WSL2使用。在原生Windows上,命令会在没有沙箱的情况下运行。