为什么需要 secrets
玩 OpenClaw 久了,你一定会往里塞各种密钥:模型服务商的 API Key、支付网关的 Secret、飞书/企业微信的 App Secret、各种第三方平台的 Token。
最容易踩的坑,是把这些明文直接写进:
- 聊天里(让 AI「帮我配一下这个 Key:sk-xxxx」)
- shell 命令的参数(
curl -H "Authorization: Bearer sk-xxxx") - 配置文件的裸字段
- 环境变量脚本,然后被
env/ 日志打印出来
这些地方的明文会出现在聊天记录、shell history、进程环境、构建日志里,任何能读到这些位置的人都能拿走。OpenClaw 提供了一套 secrets 机制,核心目标就一句:密钥明文只在受保护的共享保险库里走一遭,模型、聊天、命令参数都拿不到它。
secrets 的三条铁律
- 列表只给元数据:
secrets list返回名称、用途、允许访问的主机(allowedHosts)、更新时间,绝不返回值本身。 - 请求走人工遮罩输入:新密钥由你(人类)在遮罩框里输入,直接进共享保险库,不经过模型的上下文,也不进聊天记录。
- 配置用 SecretRef 引用:配置文件里不放明文,而是放一个引用;运行时由运行时自动注入一个不透明环境变量给需要的字段。
常用命令与示例
1. 先看已有哪些凭据
不需要记脑子,先列一遍:
secrets list
返回的是元数据清单,类似:
OPENAI_API_KEY secret api.openai.com updated 2026-09-10
FEISHU_APP_SECRET secret open.feishu.cn updated 2026-09-08
注意:这里看不到任何 sk- 开头的值,只能看到「有这么个东西、给哪个域名用」。
2. 申请一个新的凭据
格式是 secrets request,带三个关键信息:
name:大写、环境变量形态,例如STRIPE_API_KEYreason:一句话说明用途(会展示给人类)allowedHosts:精确的主机名列表(不带协议和端口),例如["api.stripe.com"]
secrets request
name: STRIPE_API_KEY
reason: 接收 Stripe 支付回调时校验签名
allowedHosts: ["api.stripe.com"]
提交后,人类在遮罩框里输入真实值,值直接进共享保险库,你拿回来的是一个 SecretRef(引用),而不是明文。之后配置里就填这个引用。
3. 删除一个不再用的凭据
secrets delete
name: OLD_PROVIDER_KEY
在配置里怎么用 SecretRef
模型服务商、网关、各种集成配置里,原本填明文 Key 的字段,改成引用形式。以模型供应商配置为例:
{
"provider": "openai",
"apiKey": { "secret": "OPENAI_API_KEY" }
}
运行时看到 { "secret": "OPENAI_API_KEY" } 就会去保险库取对应值,并自动注入一个不透明的环境变量哨兵(同名环境变量),你的代码/进程读到的是注入后的变量,不是你手敲的明文。原生 shell / sandbox / node 里没有这个受保护注入,只有网关主机命令才会自动拿到那个哨兵变量。
网关出口的两个硬约束
如果你的 OpenClaw 走网关出网,记住两点,否则密钥能存对、请求却出不去:
- 必须开启代理(proxy)+ 精确 allowedHosts:没有 allowedHosts 就禁止出网替换,配置里的 SecretRef 还能用,但出网会被拦。
- 没有明文兜底:网关出口不允许把密钥当明文回填到 URL/日志。老老实实走 SecretRef + allowedHosts。
上线前自检清单
发布任何接第三方服务的配置前,逐项打勾:
- 配置/脚本里
grep不到任何真实 Key 明文 -
secrets list能看到对应条目且 allowedHosts 精确到域名 - 聊天记录里没有贴过 Key(贴过就视为已泄露,立即轮换)
- 网关场景已开 proxy 且 allowedHosts 匹配
- 删除/替换老 Key 后,旧明文已从 history / 日志里清掉
踩过的坑(真实)
- 审批预览别带 Key:需要人工
/approve的命令,预览里只放命令本身,绝不要把 Key 拼进命令字符串当审批 id 或参数——审批界面会显示它。 - late save 要等一轮:保险库第一次被某命令读取时会给本次运行「拍快照」;如果运行中途才新存一个 Key,要等下一轮运行才能被那条命令读到,别以为当场就能用。
- shell 变量别插值明文:
export K="sk-xxx"再curl ... $K等于把明文放进环境和历史,等于没用 secrets。要么走 SecretRef 自动注入,要么干脆不在这层碰明文。 - allowedHosts 越宽越危险:只给真正要请求的域名,别图省事写
*,否则一个泄露的 Key 可能被拿去打别的站。
一句话总结
密钥管理的底线不是「藏得好」,而是「根本不出现在它不该出现的地方」。OpenClaw 的 secrets 把明文收敛到受保护保险库,配置用引用、运行用注入、列表只给元数据——照这套走,AI、日志、聊天都拿不到你的 Key。
扫码关注公众号,获取更多 OpenClaw 实操技巧:
