密钥管理

OpenClaw 支持添加性密钥引用,因此凭据不需要以明文形式存储在配置文件中?

明文仍然有效。密钥引用是可选的?

目标和运行时模型

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

  • 解析在激活时是急切的,而不是在请求路径上延迟的?
  • 如果任何引用的凭据无法解析,启动将快速失败?
  • 重新加载使用原子交换:完全成功或保持最后已知良好?
  • 运行时请求从活动的内存快照中读取?

这使密钥提供商故障远离热请求路径?

入职引用预检

当入职以交互模式运行且您选择密钥引用存储时,OpenClaw 在保存前执行快速预检查:

  • 环境引用:验证环境变量名称并确认入职期间可见非空值?
  • 提供商引用(file ?exec):验证选定的提供商,解析提供的 id,并检查值类型?

如果验证失败,入职显示错误并让您重试?

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}$

提供商配?

?secrets.providers 下定义提供商?

{
  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,
    },
  },
}

环境提供?

  • 可选通过 allowlist 的允许列表?
  • 缺失/空环境值会导致解析失败?

文件提供?

  • ?path 读取本地文件?
  • mode: "json" 期望 JSON 对象负载并将 id 解析为指针?
  • mode: "singleValue" 期望引用 id "value" 并返回文件内容?
  • 路径必须通过所有权/权限检查?

Exec 提供?

  • 运行配置的非 symlink 绝对二进制路径?
  • 默认情况下,command 必须指向常规文件(不?symlink)?
  • 设置 allowSymlinkCommand: true 以允?symlink 命令路径(例?Homebrew shims)。OpenClaw 验证解析的目标路径?
  • 仅在受信任的包管理器路径需要时启用 allowSymlinkCommand,并将其?trustedDirs 配对(例?["/opt/homebrew"])?
  • 当设?trustedDirs 时,检查应用于解析的目标路径?
  • 支持超时、无输出超时、输出字节限制、环境允许列表和受信任目录?
  • 请求负载(stdin):
{ "protocolVersion": 1, "provider": "vault", "ids": ["providers/openai/apiKey"] }
  • 响应负载(stdout):
{ "protocolVersion": 1, "values": { "providers/openai/apiKey": "sk-..." } }

可选每?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, // 需?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

{
  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

{
  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" },
      },
    },
  },
}

范围内字段(v1?

~/.openclaw/openclaw.json

  • models.providers.<provider>.apiKey
  • skills.entries.<skillKey>.apiKey
  • channels.googlechat.serviceAccount
  • channels.googlechat.serviceAccountRef
  • channels.googlechat.accounts.<accountId>.serviceAccount
  • channels.googlechat.accounts.<accountId>.serviceAccountRef

~/.openclaw/agents/<agentId>/agent/auth-profiles.json

  • profiles.<profileId>.keyRef 用于 type: "api_key"
  • profiles.<profileId>.tokenRef 用于 type: "token"

OAuth 凭据存储更改不在范围内?

必需行为和优先级

  • 无引用的字段:不变?
  • 带引用的字段:在激活时需要?
  • 如果明文和引用都存在,引用在运行时获胜,明文被忽略?

警告代码?

  • SECRETS_REF_OVERRIDES_PLAINTEXT

激活触发器

密钥激活在以下情况下尝试:

  • 启动(预检加最终激活)
  • 配置重载热应用路?
  • 配置重载重启检查路?
  • 通过 secrets.reload 手动重载

激活合约:

  • 成功原子交换快照?
  • 启动失败中止 Gateway 启动?
  • 运行时重载失败保持最后已知良好快照?

降级和恢复的 operator 信号

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

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

  • SECRETS_RELOADER_DEGRADED
  • SECRETS_RELOADER_RECOVERED

行为?

  • 降级:运行时保持最后已知良好快照?
  • 恢复:成功激活后发出一次?
  • 已经在降级时重复失败记录警告但不发送事件?
  • 启动快速失败不发出降级事件,因为尚不存在运行时快照?

审计和配置工作流

使用此默?operator 流程?

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

迁移完整性:

  • 当这些技能使?API 密钥时,包含 skills.entries.<skillKey>.apiKey 目标?
  • 如果 audit --check 在部分迁移后仍报告明文发现,迁移剩余报告的路径并重新运行审计?

secrets audit

发现包括?

  • 静态明文值(openclaw.jsonauth-profiles.json.env?
  • 未解析的引用
  • 优先级阴影(auth-profiles 优先于配置引用)
  • 旧版残留(auth.json、OAuth 超出范围提醒?

secrets configure

交互式助手:

  • 首先配置 secrets.providersenv/file/exec、添?编辑/删除?
  • 让您选择 openclaw.json 中的密钥字段
  • 捕获 SecretRef 详情(sourceproviderid?
  • 运行预检解析
  • 可以立即应用

有用的模式:

  • openclaw secrets configure --providers-only
  • openclaw secrets configure --skip-provider-setup

configure 应用默认?

  • 从目标提供商?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 有意不写包含迁移前明文密钥值的回滚备份?

安全模型?

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

auth.json 兼容性说?

对于静态凭据,OpenClaw 运行时不再依赖明?auth.json?

  • 运行时凭据来源是解析的内存快照?
  • 当发现时,旧?auth.json 静?api_key 条目被清理?
  • OAuth 相关旧版兼容性行为保持分离?

相关文档