密钥管理

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

明文仍然可用。SecretRef 是按凭证逐个选择启用的。

目标与运行时模型

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

  • 解析在激活时立即执行(eager),不是在请求路径上延迟执行(lazy)。
  • 启动时如果有效的 SecretRef 无法解析,直接快速失败。
  • 重载使用原子交换:要么全部成功,要么保持上一个已知良好的快照。
  • 运行时请求只从活跃的内存快照中读取。
  • 出站投递路径也从活跃快照中读取(例如 Discord 回复/线程投递和 Telegram action 发送),不会在每次发送时重新解析 SecretRef。

这样可以让密钥提供商的故障远离热请求路径。

活跃表面过滤

SecretRef 只在有效激活的表面上进行验证。

  • 已启用的表面:未解析的引用会阻止启动/重载。
  • 未激活的表面:未解析的引用不阻止启动/重载。
  • 未激活的引用会产生非致命诊断信息,代码为 SECRETS_REF_IGNORED_INACTIVE_SURFACE

未激活表面的例子:

  • 被禁用的通道/账户条目。
  • 没有被任何已启用账户继承的顶层通道凭证。
  • 被禁用的工具/功能表面。
  • 未被 tools.web.search.provider 选中的 Web 搜索提供商密钥。 在自动模式(provider 未设置)下,密钥按优先级逐个尝试用于提供商自动检测,直到有一个解析成功。选定后,未选中的提供商密钥视为未激活。
  • gateway.remote.token / gateway.remote.password SecretRef 在以下任一条件为真时激活:
    • gateway.mode=remote
    • 配置了 gateway.remote.url
    • gateway.tailscale.modeservefunnel
    • 在没有上述远程表面的本地模式下:
      • gateway.remote.token 在 token 认证可能生效且未配置环境变量/auth token 时激活。
      • gateway.remote.password 仅在密码认证可能生效且未配置环境变量/auth password 时激活。
  • OPENCLAW_GATEWAY_TOKEN(或 CLAWDBOT_GATEWAY_TOKEN)已设置时,gateway.auth.token SecretRef 在启动认证解析中不激活,因为环境变量 token 在该运行时优先。

网关认证表面诊断

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

  • active:该 SecretRef 是有效认证表面的一部分,必须解析成功。
  • inactive:该 SecretRef 在本次运行时被忽略,因为其他认证表面优先,或者远程认证未启用/不激活。

这些条目以 SECRETS_GATEWAY_AUTH_SURFACE 记录,包含活跃表面策略使用的原因,方便你了解为什么某个凭证被视为激活或未激活。

引导流程中的引用预检

交互式引导流程中选择 SecretRef 存储时,OpenClaw 会在保存前执行预检验证:

  • 环境变量引用:验证变量名并确认引导期间能看到非空值。
  • 提供商引用(fileexec):验证提供商选择、解析 id、检查解析后的值类型。
  • 快速启动复用路径:当 gateway.auth.token 已经是 SecretRef 时,引导流程在 probe/dashboard 引导前先解析它(对 envfileexec 引用使用相同的快速失败门控)。

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

SecretRef 合约

统一使用一种对象格式:

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

source: "env"

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

验证规则:

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

source: "file"

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

验证规则:

  • provider 必须匹配 ^[a-z][a-z0-9_-]{0,63}$
  • id 必须是绝对 JSON 指针(/...
  • RFC6901 转义规则:~ => ~0/ => ~1

source: "exec"

{ 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 会被拒绝)

提供商配置

secrets.providers 下定义提供商:

{
  secrets: {
    providers: {
      default: { source: "env" },
      filemain: {
        source: "file",
        path: "~/.openclaw/secrets.json",
        mode: "json", // or "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,
    },
  },
}

环境变量提供商

  • 可通过 allowlist 配置可选白名单。
  • 缺失或为空的环境变量值会导致解析失败。

文件提供商

  • path 指定的本地文件读取。
  • mode: "json" 期望 JSON 对象载荷,id 作为指针解析。
  • mode: "singleValue" 期望引用 id 为 "value",返回文件内容。
  • 路径必须通过所有权/权限检查。
  • Windows 注意:如果无法对某路径进行 ACL 验证,解析会失败。仅对受信路径设置 allowInsecurePath: true 来绕过路径安全检查。

Exec 提供商

  • 运行配置的绝对路径二进制文件,不经过 shell。
  • 默认情况下,command 必须指向常规文件(不是符号链接)。
  • 设置 allowSymlinkCommand: true 允许符号链接命令路径(例如 Homebrew shim)。OpenClaw 会验证解析后的目标路径。
  • allowSymlinkCommandtrustedDirs 配合使用(例如 ["/opt/homebrew"])。
  • 支持超时、无输出超时、输出字节限制、环境变量白名单和受信目录。
  • Windows 注意:如果无法对命令路径进行 ACL 验证,解析会失败。仅对受信路径设置 allowInsecurePath: true 来绕过路径安全检查。

请求载荷(stdin):

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

响应载荷(stdout):

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

可选的按 id 错误:

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

Exec 集成示例

1Password CLI

{
  secrets: {
    providers: {
      onepassword_openai: {
        source: "exec",
        command: "/opt/homebrew/bin/op",
        allowSymlinkCommand: true, // required for Homebrew symlinked binaries
        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

{
  secrets: {
    providers: {
      vault_openai: {
        source: "exec",
        command: "/opt/homebrew/bin/vault",
        allowSymlinkCommand: true, // required for Homebrew symlinked binaries
        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

{
  secrets: {
    providers: {
      sops_openai: {
        source: "exec",
        command: "/opt/homebrew/bin/sops",
        allowSymlinkCommand: true, // required for Homebrew symlinked binaries
        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" },
      },
    },
  },
}

支持的凭证覆盖范围

规范的支持和不支持凭证列表见:

运行时生成或轮换的凭证和 OAuth 刷新材料被刻意排除在只读 SecretRef 解析之外。

行为要求与优先级

  • 字段没有引用时:不变。
  • 字段有引用时:在激活表面上,激活期间必须解析成功。
  • 如果同时存在明文和引用,引用在支持的优先级路径上胜出。

警告和审计信号:

  • SECRETS_REF_OVERRIDES_PLAINTEXT(运行时警告)
  • REF_SHADOWEDauth-profiles.json 凭证优先于 openclaw.json 引用时的审计发现)

Google Chat 兼容行为:

  • serviceAccountRef 优先于明文 serviceAccount
  • 设置了同级引用时,明文值被忽略。

激活触发点

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

  • 启动(预检 + 最终激活)
  • 配置重载热更新路径
  • 配置重载重启检查路径
  • 通过 secrets.reload 手动重载

激活合约:

  • 成功时原子交换快照。
  • 启动失败时中止网关启动。
  • 运行时重载失败时保持上一个已知良好的快照。
  • 在出站辅助/工具调用中提供显式的每次调用通道 token,不触发 SecretRef 激活;激活点仍然是启动、重载和显式 secrets.reload

降级与恢复信号

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

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

  • SECRETS_RELOADER_DEGRADED
  • SECRETS_RELOADER_RECOVERED

行为:

  • 降级:运行时保持上一个已知良好的快照。
  • 恢复:在下一次成功激活后触发一次。
  • 已处于降级状态时重复失败只记录警告,不刷屏发事件。
  • 启动快速失败不触发降级事件,因为运行时从未变为活跃状态。

命令路径解析

命令路径可以通过网关快照 RPC 选择性地使用 SecretRef 解析。

有两种大类行为:

  • 严格命令路径(如 openclaw memory 远程内存路径和 openclaw qr --remote)从活跃快照读取,必需的 SecretRef 不可用时快速失败。
  • 只读命令路径(如 openclaw statusopenclaw status --allopenclaw channels statusopenclaw channels resolve 以及只读的 doctor/config 修复流程)也优先使用活跃快照,但在目标 SecretRef 不可用时降级而非中止。

只读行为:

  • 网关运行时,这些命令先从活跃快照读取。
  • 如果网关解析不完整或网关不可用,它们会尝试对特定命令表面进行本地回退。
  • 如果目标 SecretRef 仍不可用,命令继续运行但输出降级的只读结果,并显示明确诊断信息如”已配置但在此命令路径中不可用”。
  • 这种降级行为仅限命令本身。它不会削弱运行时启动、重载或发送/认证路径。

其他说明:

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

审计与配置工作流

默认操作员流程:

openclaw secrets audit --check
openclaw secrets configure
openclaw secrets audit --check

secrets audit

发现项包括:

  • 静态存储中的明文值(openclaw.jsonauth-profiles.json.env 以及生成的 agents/*/agent/models.json
  • 生成的 models.json 条目中的明文敏感提供商 header 残留
  • 未解析的引用
  • 优先级遮蔽(auth-profiles.json 优先于 openclaw.json 引用)
  • 历史遗留残留(auth.json、OAuth 提醒)

Header 残留说明:

  • 敏感提供商 header 检测基于名称启发式(常见的认证/凭证 header 名称和片段如 authorizationx-api-keytokensecretpasswordcredential)。

secrets configure

交互式助手,功能包括:

  • 首先配置 secrets.providersenv/file/exec,添加/编辑/删除)
  • 选择 openclaw.json 和某个 agent 范围下 auth-profiles.json 中的密钥字段
  • 可以在目标选择器中直接创建新的 auth-profiles.json 映射
  • 采集 SecretRef 详情(sourceproviderid
  • 运行预检解析
  • 可以立即应用

快捷模式:

  • openclaw secrets configure --providers-only
  • openclaw secrets configure --skip-provider-setup
  • openclaw secrets configure --agent <id>

configure apply 默认行为:

  • 为目标提供商擦除 auth-profiles.json 中匹配的静态凭证
  • 擦除 auth.json 中旧版静态 api_key 条目
  • 擦除 <config-dir>/.env 中匹配的已知密钥行

secrets apply

应用保存的计划:

openclaw secrets apply --from /tmp/openclaw-secrets-plan.json
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --dry-run

严格的目标/路径合约和详细的拒绝规则见:

单向安全策略

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

安全模型:

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

旧版认证兼容说明

对于静态凭证,运行时不再依赖明文旧版认证存储。

  • 运行时凭证来源是解析后的内存快照。
  • 发现旧版静态 api_key 条目时自动擦除。
  • OAuth 相关的兼容行为保持独立。

Web UI 说明

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

相关文档