Skip to content

SecretRef 是 OpenClaw 的凭据引用机制,将 API Key 等敏感信息解析到运行时内存快照,无需存为明文。配置时使用 { source, provider, id } 对象,支持环境变量、本地文件和外部命令三种来源。启动或重载时,活跃的 SecretRef 必须解析成功,否则快速失败。通过 openclaw secrets audit --check 可以扫描明文残留和未解析 ref,配合 openclaw secrets configure 交互式迁移。exec 集成示例包括 1Password CLI、Vault CLI 和 sops。单向安全策略:不写入包含历史明文值的回滚备份。

OpenClaw 密钥管理(SecretRef)配置与审计指南

OpenClaw 支持增量式 SecretRef,让受支持的凭据无需以明文形式存储在配置中。

INFO

明文方式依然可用,SecretRef 是逐字段可选的。

目标与运行时模型

密钥被解析到内存中的运行时快照。

  • 解析在激活期间立即执行,而不是延迟到请求路径上。
  • 若有效活跃的 SecretRef 无法解析,启动时快速失败
  • 重新加载使用原子交换:完全成功,或保留上一次已知正确快照。
  • SecretRef 策略违规(例如 OAuth 模式的 auth profiles 与 SecretRef 输入组合)在运行时交换前就会失败激活。
  • 运行时请求只从活跃的内存快照读取。
  • 在第一次成功配置激活/加载后,运行时代码路径持续读取该活跃内存快照,直到下次成功重载替换它。
  • 出站投递路径(例如 Discord 回复/线程投递和 Telegram 动作发送)也从该活跃快照读取,不会在每次发送时重新解析 SecretRef。

这让密钥提供商中断不会影响热请求路径。

活跃面过滤

SecretRef 仅在有效活跃的面上验证。

  • 已启用的面:未解析的 ref 会阻断启动/重新加载。
  • 未活跃的面:未解析的 ref 不会阻断启动/重新加载。
  • 未活跃的 ref 会触发非致命诊断,代码为 SECRETS_REF_IGNORED_INACTIVE_SURFACE

未活跃面的示例

- 已禁用的频道/账户条目。
- 没有已启用账户继承的顶层频道凭据。
- 已禁用的工具/功能面。
- 未被 `tools.web.search.provider` 选中的 Web 搜索 provider 专属 key。在自动模式(未设置 provider)下,key 按优先级顺序用于 provider 自动检测,直到有一个解析成功。选定后,未被选中的 provider key 将被视为未活跃直到被选中。
- 沙盒 SSH 认证材料(`agents.defaults.sandbox.ssh.identityData`、`certificateData`、`knownHostsData`,以及按 Agent 覆盖)仅在默认 Agent 或已启用 Agent 的有效沙盒后端为 `ssh` 时活跃。
- 满足以下任一条件时,`gateway.remote.token` / `gateway.remote.password` SecretRef 活跃:
  - `gateway.mode=remote`
  - 配置了 `gateway.remote.url`
  - `gateway.tailscale.mode` 为 `serve` 或 `funnel`
  - 在不具备上述远端面的本地模式下:
    - 当 token auth 可以胜出且未配置 env/auth token 时,`gateway.remote.token` 活跃。
    - 当 password auth 可以胜出且未配置 env/auth password 时,`gateway.remote.password` 活跃。
- 当设置了 `OPENCLAW_GATEWAY_TOKEN` 时,`gateway.auth.token` SecretRef 对启动 auth 解析而言是未活跃的,因为 env token 输入在该运行时中优先。

Gateway auth 面诊断

gateway.auth.tokengateway.auth.passwordgateway.remote.tokengateway.remote.password 上配置了 SecretRef 时,Gateway 启动/重新加载会显式记录面状态:

  • active:SecretRef 是有效 auth 面的一部分,必须解析成功。
  • inactive:由于另一个 auth 面优先,或远端 auth 未启用/不活跃,该 SecretRef 在本次运行时被忽略。

这些条目以 SECRETS_GATEWAY_AUTH_SURFACE 记录,并包含活跃面策略使用的原因,方便你了解凭据为何被视为活跃或未活跃。

引导参考预检

当引导流程以交互模式运行且你选择 SecretRef 存储时,OpenClaw 在保存前运行预检验证:

  • Env ref:验证环境变量名,并确认在配置期间有可见的非空值。
  • Provider ref(fileexec):验证 provider 选择,解析 id,检查解析值类型。
  • Quickstart 复用路径:若 gateway.auth.token 已是 SecretRef,引导流程在 probe/dashboard 引导启动前解析它(对 envfileexec ref 使用相同的快速失败门禁)。

验证失败时,引导流程会显示错误并允许重试。

SecretRef 合约

处处使用同一个对象格式:

json5
{ source: "env" | "file" | "exec", provider: "default", id: "..." }

env

```json5
{ source: "env", provider: "default", id: "OPENAI_API_KEY" }
```

支持的 SecretInput 字段也接受精确字符串简写:

```json5
"${OPENAI_API_KEY}"
"$OPENAI_API_KEY"
```

验证规则:

- `provider` 必须匹配 `^[a-z][a-z0-9_-]{0,63}$`
- `id` 必须匹配 `^[A-Z][A-Z0-9_]{0,127}$`

file

```json5
{ source: "file", provider: "filemain", id: "/providers/openai/apiKey" }
```

验证规则:

- `provider` 必须匹配 `^[a-z][a-z0-9_-]{0,63}$`
- `id` 必须是绝对 JSON pointer(`/...`)
- 段中 RFC6901 转义:`~` => `~0`,`/` => `~1`

exec

```json5
{ source: "exec", provider: "vault", id: "providers/openai/apiKey" }
```

验证规则:

- `provider` 必须匹配 `^[a-z][a-z0-9_-]{0,63}$`
- `id` 必须匹配 `^[A-Za-z0-9][A-Za-z0-9._:/-]{0,255}$`
- `id` 不得包含以斜杠分隔的 `.` 或 `..` 路径段(例如 `a/../b` 会被拒绝)

Provider 配置

secrets.providers 下定义 provider:

json5
{
  secrets: {
    providers: {
      default: { source: "env" },
      filemain: {
        source: "file",
        path: "~/.openclaw/secrets.json",
        mode: "json", // 或 "singleValue"
      },
      vault: {
        source: "exec",
        command: "/usr/local/bin/openclaw-vault-resolver",
        args: ["--profile", "prod"],
        passEnv: ["PATH", "VAULT_ADDR"],
        jsonOnly: true,
      },
    },
    defaults: {
      env: "default",
      file: "filemain",
      exec: "vault",
    },
    resolution: {
      maxProviderConcurrency: 4,
      maxRefsPerProvider: 512,
      maxBatchBytes: 262144,
    },
  },
}

Env provider

- 可选的 `allowlist` 白名单。
- 缺失/空环境变量值会导致解析失败。

File provider

- 从 `path` 读取本地文件。
- `mode: "json"` 期望 JSON 对象载荷,以指针解析 `id`。
- `mode: "singleValue"` 期望 ref id 为 `"value"`,返回文件内容。
- 路径必须通过所有权/权限检查。
- Windows 安全关闭注意:若路径的 ACL 验证不可用,解析失败。对于受信路径,可在该 provider 设置 `allowInsecurePath: true` 绕过路径安全检查。

Exec provider

- 运行配置的绝对二进制路径,不使用 shell。
- 默认情况下,`command` 必须指向普通文件(非软链接)。
- 设置 `allowSymlinkCommand: true` 允许软链接命令路径(例如 Homebrew shim)。OpenClaw 会验证解析后的目标路径。
- 将 `allowSymlinkCommand` 与 `trustedDirs` 组合用于包管理器路径(例如 `["/opt/homebrew"]`)。
- 支持超时、无输出超时、输出字节限制、env 白名单和受信目录。
- Windows 安全关闭注意:若命令路径的 ACL 验证不可用,解析失败。对于受信路径,可设置 `allowInsecurePath: true` 绕过路径安全检查。

请求载荷(stdin):

```json
{ "protocolVersion": 1, "provider": "vault", "ids": ["providers/openai/apiKey"] }
```

响应载荷(stdout):

```jsonc
{ "protocolVersion": 1, "values": { "providers/openai/apiKey": "<openai-api-key>" } } // pragma: allowlist secret
```

可选的按 id 错误:

```json
{
  "protocolVersion": 1,
  "values": {},
  "errors": { "providers/openai/apiKey": { "message": "not found" } }
}
```

文件型 API Key

不要将 file:... 字符串放在配置的 env 块中。env 块是字面量且不可覆盖,file:... 不会被解析。

改用文件 SecretRef 放在受支持的凭据字段上:

json5
{
  secrets: {
    providers: {
      xai_key_file: {
        source: "file",
        path: "~/.openclaw/secrets/xai-api-key.txt",
        mode: "singleValue",
      },
    },
  },
  models: {
    providers: {
      xai: {
        apiKey: { source: "file", provider: "xai_key_file", id: "value" },
      },
    },
  },
}

对于 mode: "singleValue",SecretRef id"value"。对于 mode: "json",使用绝对 JSON pointer,例如 "/providers/xai/apiKey"

可接受 SecretRef 的配置字段列表参见 SecretRef 凭据面

Exec 集成示例

1Password CLI

```json5
{
  secrets: {
    providers: {
      onepassword_openai: {
        source: "exec",
        command: "/opt/homebrew/bin/op",
        allowSymlinkCommand: true, // Homebrew 软链接二进制必须
        trustedDirs: ["/opt/homebrew"],
        args: ["read", "op://Personal/OpenClaw QA API Key/password"],
        passEnv: ["HOME"],
        jsonOnly: false,
      },
    },
  },
  models: {
    providers: {
      openai: {
        baseUrl: "https://api.openai.com/v1",
        models: [{ id: "gpt-5", name: "gpt-5" }],
        apiKey: { source: "exec", provider: "onepassword_openai", id: "value" },
      },
    },
  },
}
```

HashiCorp Vault CLI

```json5
{
  secrets: {
    providers: {
      vault_openai: {
        source: "exec",
        command: "/opt/homebrew/bin/vault",
        allowSymlinkCommand: true, // Homebrew 软链接二进制必须
        trustedDirs: ["/opt/homebrew"],
        args: ["kv", "get", "-field=OPENAI_API_KEY", "secret/openclaw"],
        passEnv: ["VAULT_ADDR", "VAULT_TOKEN"],
        jsonOnly: false,
      },
    },
  },
  models: {
    providers: {
      openai: {
        baseUrl: "https://api.openai.com/v1",
        models: [{ id: "gpt-5", name: "gpt-5" }],
        apiKey: { source: "exec", provider: "vault_openai", id: "value" },
      },
    },
  },
}
```

sops

```json5
{
  secrets: {
    providers: {
      sops_openai: {
        source: "exec",
        command: "/opt/homebrew/bin/sops",
        allowSymlinkCommand: true, // Homebrew 软链接二进制必须
        trustedDirs: ["/opt/homebrew"],
        args: ["-d", "--extract", '["providers"]["openai"]["apiKey"]', "/path/to/secrets.enc.json"],
        passEnv: ["SOPS_AGE_KEY_FILE"],
        jsonOnly: false,
      },
    },
  },
  models: {
    providers: {
      openai: {
        baseUrl: "https://api.openai.com/v1",
        models: [{ id: "gpt-5", name: "gpt-5" }],
        apiKey: { source: "exec", provider: "sops_openai", id: "value" },
      },
    },
  },
}
```

MCP 服务器环境变量

通过 plugins.entries.acpx.config.mcpServers 配置的 MCP 服务器环境变量支持 SecretInput。这可以把 API Key 和 token 移出明文配置:

json5
{
  plugins: {
    entries: {
      acpx: {
        enabled: true,
        config: {
          mcpServers: {
            github: {
              command: "npx",
              args: ["-y", "@modelcontextprotocol/server-github"],
              env: {
                GITHUB_PERSONAL_ACCESS_TOKEN: {
                  source: "env",
                  provider: "default",
                  id: "MCP_GITHUB_PAT",
                },
              },
            },
          },
        },
      },
    },
  },
}

明文字符串仍然可用。Env 模板引用如 ${MCP_SERVER_API_KEY} 和 SecretRef 对象会在 Gateway 激活期间、MCP 服务器进程启动前被解析。与其他 SecretRef 面一样,未解析的 ref 仅在 acpx 插件有效活跃时阻断激活。

沙盒 SSH 认证材料

核心 ssh 沙盒后端也支持 SSH 认证材料的 SecretRef:

json5
{
  agents: {
    defaults: {
      sandbox: {
        mode: "all",
        backend: "ssh",
        ssh: {
          target: "user@gateway-host:22",
          identityData: { source: "env", provider: "default", id: "SSH_IDENTITY" },
          certificateData: { source: "env", provider: "default", id: "SSH_CERTIFICATE" },
          knownHostsData: { source: "env", provider: "default", id: "SSH_KNOWN_HOSTS" },
        },
      },
    },
  },
}

运行时行为:

  • OpenClaw 在沙盒激活期间解析这些 ref,而不是在每次 SSH 调用时延迟解析。
  • 解析的值写入具有严格权限的临时文件,并用于生成的 SSH 配置。
  • 若有效的沙盒后端不是 ssh,这些 ref 保持未活跃状态,不会阻断启动。

支持的凭据面

支持和不支持的凭据的权威列表见 SecretRef 凭据面

INFO

运行时铸造的或轮换中的凭据以及 OAuth 刷新材料,有意从只读 SecretRef 解析中排除。

必须行为与优先级

  • 没有 ref 的字段:保持不变。
  • 有 ref 的字段:在激活期间的活跃面上必须解析成功。
  • 若明文和 ref 同时存在,在支持优先级路径上 ref 优先。
  • 遮蔽哨兵 __OPENCLAW_REDACTED__ 预留给内部配置遮蔽/恢复使用,作为提交的字面配置数据会被拒绝。

警告和审计信号:

  • SECRETS_REF_OVERRIDES_PLAINTEXT(运行时警告)
  • REF_SHADOWED(当 auth-profiles.json 凭据优先于 openclaw.json ref 时的审计发现)

Google Chat 兼容行为:

  • serviceAccountRef 优先于明文 serviceAccount
  • 设置了 sibling ref 时忽略明文值。

激活触发点

密钥激活在以下时机运行:

  • 启动(预检 + 最终激活)
  • 配置热加载路径
  • 配置重载重启检查路径
  • 通过 secrets.reload 手动重载
  • Gateway 配置写入 RPC 预检(config.set / config.apply / config.patch)会在持久化前对提交配置中的活跃面 SecretRef 可解析性进行验证

激活规范:

  • 成功时原子交换快照。
  • 启动失败时中止 Gateway 启动。
  • 运行时重载失败时保留上一次已知正确快照。
  • 写入 RPC 预检失败会拒绝提交的配置,同时保持磁盘配置和运行时快照不变。
  • 为出站 helper/tool 调用提供显式的按调用 channel token 不触发 SecretRef 激活;激活点仍为启动、重载和显式 secrets.reload

降级与恢复信号

重载时激活失败(在健康状态后),OpenClaw 进入密钥降级状态。

一次性系统事件和日志代码:

  • SECRETS_RELOADER_DEGRADED
  • SECRETS_RELOADER_RECOVERED

行为:

  • 降级:运行时保留上一次已知正确快照。
  • 恢复:下次成功激活后触发一次。
  • 已处于降级状态时重复失败会记录警告,但不会重复发送事件。
  • 启动快速失败不触发降级事件,因为运行时从未变为活跃状态。

命令路径解析

命令路径可通过 Gateway 快照 RPC 选择加入受支持的 SecretRef 解析。

有两种宽泛的行为:

严格命令路径

例如 `openclaw memory` 远端内存路径和 `openclaw qr --remote`(当需要远端共享密钥 ref 时)。它们从活跃快照读取,在所需 SecretRef 不可用时快速失败。

只读命令路径

例如 `openclaw status`、`openclaw status --all`、`openclaw channels status`、`openclaw channels resolve`、`openclaw security audit`,以及只读 doctor/config repair 流程。它们也优先使用活跃快照,但在该命令路径中目标 SecretRef 不可用时降级,而不是中止。

只读行为:

- Gateway 运行时,这些命令优先从活跃快照读取。
- 若 Gateway 解析不完整或 Gateway 不可用,对特定命令面尝试目标化的本地回退。
- 若目标 SecretRef 仍不可用,命令继续运行并输出降级的只读结果,附带明确诊断信息(如“在此命令路径中已配置但不可用”)。
- 此降级行为仅限当前命令,不会削弱运行时启动、重载或发送/auth 路径。

其他说明:

  • 后端密钥轮换后刷新快照通过 openclaw secrets reload 处理。
  • 这些命令路径使用的 Gateway RPC 方法:secrets.resolve

审计与配置工作流

默认 operator 流程:

审计当前状态

```bash
openclaw secrets audit --check
```

配置 SecretRef

```bash
openclaw secrets configure
```

重新审计

```bash
openclaw secrets audit --check
```

secrets audit

审计发现包括:

- 明文存储的值(`openclaw.json`、`auth-profiles.json`、`.env` 及生成的 `agents/*/agent/models.json`)
- 生成的 `models.json` 条目中明文敏感 provider header 残留
- 未解析的 ref
- 优先级遮蔽(`auth-profiles.json` 优先于 `openclaw.json` ref)
- 遗留残留(`auth.json`、OAuth 提醒)

Exec 注意:

- 默认情况下,audit 跳过 exec SecretRef 可解析性检查,以避免命令副作用。
- 使用 `openclaw secrets audit --allow-exec` 在 audit 期间执行 exec provider。

Header 残留注意:

- 敏感 provider header 检测基于名称启发式(常见 auth/凭据 header 名称和片段,如 `authorization`、`x-api-key`、`token`、`secret`、`password`、`credential`)。

secrets configure

交互式助手,功能包括:

- 优先配置 `secrets.providers`(`env`/`file`/`exec`,添加/编辑/删除)
- 在 `openclaw.json` 和 `auth-profiles.json`(一个 agent 作用域)中选择受支持的密钥字段
- 可直接在目标选择器中创建新的 `auth-profiles.json` 映射
- 采集 SecretRef 详情(`source`、`provider`、`id`)
- 运行预检解析
- 可立即应用

Exec 注意:

- 除非设置了 `--allow-exec`,预检跳过 exec SecretRef 检查。
- 若从 `configure --apply` 直接应用且计划包含 exec ref/provider,apply 步骤也要保持 `--allow-exec`。

实用模式:

- `openclaw secrets configure --providers-only`
- `openclaw secrets configure --skip-provider-setup`
- `openclaw secrets configure --agent &lt;id&gt;`

`configure` 应用默认行为:

- 清理 `auth-profiles.json` 中目标 provider 的匹配静态凭据
- 清理 `auth.json` 中遗留的静态 `api_key` 条目
- 清理 `&lt;config-dir&gt;/.env` 中已知的密钥行

secrets apply

应用已保存的计划:

```bash
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --allow-exec
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --dry-run
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --dry-run --allow-exec
```

Exec 注意:

- dry-run 默认跳过 exec 检查,除非设置了 `--allow-exec`。
- 包含 exec SecretRef/provider 的计划在写入模式下被拒绝,除非设置了 `--allow-exec`。

严格目标/路径规范和确切拒绝规则详见 [Secrets Apply 计划规范](/ai/ai-tools/openclaw/gateway/secrets-plan-contract)。

单向安全策略

WARNING

OpenClaw 有意不写入包含历史明文密钥值的回滚备份。

安全模型:

  • 预检必须在写入模式前成功
  • 在提交前验证运行时激活
  • apply 使用原子文件替换更新文件,失败时尽力恢复

遗留 auth 兼容说明

对于静态凭据,运行时不再依赖明文遗留 auth 存储。

  • 运行时凭据来源是已解析的内存快照。
  • 发现遗留静态 api_key 条目时会被清理。
  • OAuth 相关兼容行为保持独立。

Web UI 说明

部分 SecretInput union 在原始编辑器模式下比表单模式更容易配置。

相关文档

常见问题

SecretRef 解析失败怎么办?

启动时如果活跃面 SecretRef 无法解析,Gateway 会快速失败并停止,日志可定位未解析的 ref。运行时重载失败则保留上一次成功快照,不中断已有连接。首先检查环境变量是否存在且非空、文件路径和权限是否正确、exec 命令能否独立运行。使用 openclaw secrets audit --check 可扫描未解析 ref 和明文残留。

openclaw secrets audit 和 configure 怎么用?

openclaw secrets audit --check 扫描配置文件中明文存储的凭据、未解析的 SecretRef 以及优先级遮蔽问题。openclaw secrets configure 是交互式助手,允许选择凭据字段,配置 providers(env/file/exec),并立即应用。应用时会自动清理 auth-profiles.jsonauth.json.env 中的明文版本。对于 exec provider,默认跳过可解析性检查,使用 --allow-exec 包括。

SecretRef 和明文同时存在时谁优先?

在支持优先级的路径上,SecretRef 优先于明文。如果配置了 SecretRef 且同字段也有明文值,运行时会发出 SECRETS_REF_OVERRIDES_PLAINTEXT 警告。如果 auth-profiles.json 中的静态凭据比 openclaw.json 的 SecretRef 更优先,审计会发现 REF_SHADOWED