OpenClaw 凭据与密钥管理机制
基于源码分析,OpenClaw 采用多层次的凭据管理体系,核心设计思路是:文件权限 + 引用解耦 + 运行时隔离 + 审计检测。
全景图
凭据来源
│
├── 用户手动配置(CLI / Web UI)
├── 外部 CLI 同步(Claude / Codex / Qwen / MiniMax)
└── Secret Ref 引用(env / file / exec)
│
▼
[存储层] auth-profiles.json ── 0o600 文件权限,无静态加密
│
▼
[解析层] Secret Ref 系统 ── 按 env/file/exec 解析引用,校验文件权限
│
▼
[运行时层] 只读快照 + 环境变量清洗 + 配置脱敏
│
▼
[审计层] 明文检测 / 未解析引用 / 遗留文件扫描
1. 存储机制
1.1 主存储:Auth Profiles
源码位置: src/agents/auth-profiles/
持久化路径:
- 主 agent:
~/.openclaw/auth-profiles.json - 子 agent:
/auth-profiles.json
支持三种凭据类型:
| 类型 | 字段 | 说明 |
|---|---|---|
| `api_key` | `key` | 直接 API 密钥 |
| `token` | `token`, `expires` | Bearer token,含可选过期时间 |
| `oauth` | `access`, `refresh`, `expires` | OAuth 凭据(access/refresh/expires) |
- 每个 profile 以
"provider:profileId"为键(如"openai:default") - 子 agent 各自有独立的
auth-profiles.json,为空时自动继承主 agent 凭据 - 包含元数据:
order(优先级)、lastGood(回退追踪)、usageStats(使用统计)
1.2 存储操作
源码位置: src/agents/auth-profiles/store.ts
| 函数 | 说明 |
|---|---|
| `loadAuthProfileStore()` | 加载并自动迁移旧版 auth.json |
| `loadAuthProfileStoreForRuntime()` | 加载并继承主 agent 凭据 |
| `saveAuthProfileStore()` | 带文件锁保存(10 次重试) |
| `updateAuthProfileStoreWithLock()` | 原子更新操作 |
写入时使用 withFileLock() 确保并发安全。
1.3 旧版兼容
- 旧版路径:
~/.openclaw/credentials/oauth.json(可通过OPENCLAW_OAUTH_DIR覆盖) - 还支持更早期的路径:
~/.clawdbot、~/.moldbot、~/.moltbot - 加载时自动迁移到 auth-profiles 格式
- 审计工具可检测迁移后遗留的旧文件(
LEGACY_RESIDUE)
2. 文件权限保护
2.1 存储文件权限
源码位置: src/infra/json-file.ts
fs.mkdirSync(dir, { recursive: true, mode: 0o700 }); // 目录:仅 owner 可 rwx
fs.chmodSync(pathname, 0o600); // 文件:仅 owner 可 rw
Auth JSON 文件同样使用 0o600(src/agents/pi-auth-json.ts)。
> 注意:没有静态加密,完全依赖 OS 文件权限做用户隔离。macOS 上可选通过 Keychain 存储(仅用于外部 CLI 凭据同步场景)。
2.2 Secret 文件安全校验
源码位置: src/secrets/resolve.ts
对 file 类型的 Secret Ref,执行以下校验:
- 必须为绝对路径
- 不可 world-writable 或 group-writable
- 不可 group-readable(除非显式允许)
- 必须归当前用户所有(POSIX)
- 符号链接仅在解析目标安全时允许
- Windows 环境下有 ACL 校验
3. 环境变量安全
3.1 危险环境变量拦截
源码位置: src/infra/host-env-security.ts
三层过滤机制:
| 层级 | 规则 | 示例 |
|---|---|---|
| 硬编码黑名单 | 指定变量名 | `AWS_SECRET_ACCESS_KEY`, `GH_TOKEN`, `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `TELEGRAM_BOT_TOKEN` |
| 后缀匹配 | `_API_KEY`, `_TOKEN`, `_PASSWORD`, `_SECRET`, `_PRIVATE_KEY` | `CUSTOM_API_KEY`, `MY_SERVICE_TOKEN` |
| 前缀匹配 | `AWS_`, `AZURE_` 等 | `AWS_SESSION_TOKEN`, `AZURE_CLIENT_SECRET` |
主要函数:
isDangerousHostEnvVarName()— 判定变量是否危险sanitizeHostExecEnv()— 在执行子进程前移除危险变量sanitizeSystemRunEnvOverrides()— 过滤 shell wrapper 的环境变量覆盖
Shell wrapper 只允许:TERM, LANG, LC_*, COLORTERM, NO_COLOR, FORCE_COLOR。
3.2 沙箱环境变量清洗
源码位置: src/agents/sandbox/sanitize-env-vars.ts
执行子进程前的额外清洗:
- 移除所有已知敏感变量(
ANTHROPIC_API_KEY,OPENAI_API_KEY,GEMINI_API_KEY等) - 移除频道凭据(
TELEGRAM_BOT_TOKEN,DISCORD_BOT_TOKEN,SLACK_BOT_TOKEN) - 移除 gateway 凭据(
OPENCLAW_GATEWAY_TOKEN,OPENCLAW_GATEWAY_PASSWORD) - 检测并过滤疑似 Base64 编码的长值(>80 字符的字母数字/+/= 序列)
- Null byte 过滤
3.3 环境变量替换
源码位置: src/config/env-vars.ts
- 配置中可通过
${VAR_NAME}语法引用环境变量 - 替换在配置加载后、使用前执行
containsEnvVarReference()检测未解析的${VAR}引用,未解析的引用会被拒绝(防止占位符字符串被当作凭据使用)
4. Secret Reference 系统
源码位置: src/secrets/, src/config/types.secrets.ts
提供三种引用源,避免在配置中硬编码明文:
4.1 env 类型
{ "source": "env", "provider": "default", "id": "VAR_NAME" }
或简写语法 ${VAR_NAME}。从环境变量读取。
4.2 file 类型
两种模式:
| 模式 | 说明 |
|---|---|
| `singleValue` | 读取整个文件内容作为 secret |
| `json` | 解析 JSON 文件,通过 JSON pointer 提取指定字段 |
读取前会执行第 2 节所述的文件安全校验。
4.3 exec 类型
执行命令并解析输出(支持 JSON 或原始文本)。审计时使用静态错误策略(跳过实际执行)。
5. 凭据审计
源码位置: src/secrets/audit.ts
自动化扫描能力,检测以下问题:
| 检测项 | 说明 |
|---|---|
| `PLAINTEXT_FOUND` | 配置/auth 文件中存在明文凭据 |
| `REF_UNRESOLVED` | Secret Ref 引用的 provider 缺失 |
| `REF_SHADOWED` | 明文覆盖了 Secret Ref(应该用 Ref 但实际存了明文) |
| `LEGACY_RESIDUE` | 迁移后遗留的旧 auth.json 文件 |
检测模式:匹配 header 中的 api-key、token、secret、password、credential 等模式。并发解析(8 worker 并发)。
Secret 应用
源码位置: src/secrets/apply.ts
| 功能 | 说明 |
|---|---|
| dry-run 模式 | 预览变更,不写入 |
| write 模式 | 原子文件更新 |
| 可解析性校验 | 写入前验证所有 Ref 可正常解析 |
| 变更追踪 | 记录变更文件和脱敏值 |
| 值校验 | `assertExpectedResolvedSecretValue()` |
6. 运行时安全
6.1 只读快照
源码位置: src/secrets/runtime.ts
- 运行时使用已解析的只读 secret 快照
- 禁用 Keychain 访问
- 禁用外部 CLI 同步
- 包含动态刷新 handler(用于 OAuth token 续期等场景)
- 内容包括:已解析的配置值、每个 agent 的 auth profile 快照、Web tools 元数据
6.2 配置脱敏
源码位置: src/config/redact-snapshot.ts
- 哨兵值:
__OPENCLAW_REDACTED__ - 通过 Web UI / API 返回配置时,敏感字段替换为哨兵值
- 读取端 handler 从磁盘恢复原始值
- 防止配置在 round-trip 传输中被破坏或泄露
6.3 输入规范化
源码位置: src/utils/normalize-secret-input.ts
对用户粘贴的凭据输入做规范化:
- 移除换行符:
\r,\n, Unicode 行分隔符 - 过滤非 Latin1 字符(丢弃 codepoint > 0xFF)
- 修剪首尾空白
- 保留内部空格
6.4 Token 过期管理
源码位置: src/agents/pi-auth-credentials.ts, src/agents/auth-profiles/oauth.ts
- 运行时自动过滤已过期的 token
- OAuth token 支持带文件锁的自动刷新
- 主 agent 的新 token 可向下传递给子 agent
- JWT 过期时间解码(
src/agents/cli-credentials.ts)
7. 外部 CLI 凭据同步
源码位置: src/agents/cli-credentials.ts
自动从主流 AI CLI 工具同步凭据:
| CLI 工具 | 文件路径 | macOS Keychain |
|---|---|---|
| Claude CLI | `~/.claude/.credentials.json` | 支持(service: `Claude Code-credentials`) |
| Codex CLI | `~/.codex/auth.json` | 支持(account: sha256 hash) |
| Qwen CLI | `~/.qwen/oauth_creds.json` | 不支持 |
| MiniMax CLI | `~/.minimax/oauth_creds.json` | 不支持 |
- 带 TTL 缓存(默认 15 分钟),避免频繁读取
- 每次加载 auth-profiles 时自动触发同步
- macOS Keychain 读写函数:
writeClaudeCliKeychainCredentials(),readClaudeCliCredentials()
8. Gateway 凭据解析
源码位置: src/gateway/credentials.ts
Gateway 凭据解析遵循优先级链(默认 env-first 模式):
1. CLI flags (--token, --password) ← 最高优先级
2. 环境变量 (OPENCLAW_GATEWAY_TOKEN, OPENCLAW_GATEWAY_PASSWORD)
3. 配置文件 (gateway.auth.token, gateway.auth.password)
4. 远程 gateway 回退 ← 最低优先级
也支持 config-first 模式(配置文件优先于环境变量)。
主要函数:
resolveGatewayCredentialsFromConfig()— 主解析器resolveGatewayCredentialsFromValues()— 简单优先级逻辑
关键文件索引
| 路径 | 职责 |
|---|---|
| `src/agents/auth-profiles/` | Auth profile 存储、加载、迁移、OAuth 刷新 |
| `src/agents/auth-profiles/store.ts` | profile 存储操作(加载/保存/文件锁) |
| `src/agents/auth-profiles/oauth.ts` | OAuth token 刷新与锁定 |
| `src/agents/auth-profiles/constants.ts` | 常量定义(文件名等) |
| `src/agents/cli-credentials.ts` | 外部 CLI 凭据同步与 Keychain 操作 |
| `src/agents/pi-auth-credentials.ts` | Auth profile → Pi 运行时格式转换 |
| `src/agents/sandbox/sanitize-env-vars.ts` | 沙箱环境变量清洗 |
| `src/config/paths.ts` | 配置和 OAuth 目录路径解析 |
| `src/config/env-vars.ts` | 环境变量 `${VAR}` 替换 |
| `src/config/redact-snapshot.ts` | 配置脱敏(`__OPENCLAW_REDACTED__`) |
| `src/config/types.secrets.ts` | Secret Ref 类型定义(env/file/exec) |
| `src/secrets/resolve.ts` | Secret 解析与文件权限校验 |
| `src/secrets/audit.ts` | 凭据审计扫描 |
| `src/secrets/apply.ts` | Secret 应用(dry-run/write) |
| `src/secrets/runtime.ts` | 运行时只读快照 |
| `src/infra/json-file.ts` | 安全 JSON 文件 I/O(mode 0o600) |
| `src/infra/host-env-security.ts` | 危险环境变量拦截 |
| `src/gateway/credentials.ts` | Gateway 凭据解析(优先级链) |
| `src/utils/normalize-secret-input.ts` | Secret 输入规范化 |
总结
OpenClaw 的凭据管理采用务实的分层策略,不依赖重量级加密方案,而是通过多层防线协同保护:
1. 存储层:JSON 文件 + 0o600 权限,依赖 OS 用户隔离
2. 引用层:Secret Ref 系统(env/file/exec),将明文从配置中解耦
3. 运行时层:只读快照 + 环境变量清洗 + 配置脱敏,防止凭据泄露到子进程或 API 响应
4. 审计层:自动化扫描检测明文泄露、未解析引用和遗留文件
5. 外部集成:自动同步主流 AI CLI 工具的凭据,支持 macOS Keychain
6. 并发安全:文件锁 + 原子更新,支持多 agent 并发操作