シークレット管理

OpenClaw は追加型の SecretRef をサポートしており、サポート対象のクレデンシャルを設定に平文で保存する必要がありません。

平文も引き続き使用可能です。SecretRef はクレデンシャルごとにオプトインです。

目的とランタイムモデル

シークレットはインメモリのランタイムスナップショットに解決されます。

  • 解決はアクティベーション時に即座に行われ、リクエストパス上で遅延解決されることはありません。
  • 有効にアクティブな SecretRef が解決できない場合、起動は即座に失敗します。
  • リロードはアトミックスワップを使用します:完全に成功するか、最後の正常なスナップショットを維持するかのいずれかです。
  • ランタイムリクエストはアクティブなインメモリスナップショットのみから読み取ります。
  • 送信配信パスも同じアクティブスナップショットから読み取ります(例:Discord の返信/スレッド配信や Telegram のアクション送信)。送信ごとに SecretRef を再解決することはありません。

これにより、シークレットプロバイダーの障害がホットリクエストパスに影響しません。

アクティブサーフェスフィルタリング

SecretRef は有効にアクティブなサーフェスでのみ検証されます。

  • 有効なサーフェス:未解決の ref は起動/リロードをブロックします。
  • 非アクティブなサーフェス:未解決の ref は起動/リロードをブロックしません。
  • 非アクティブな ref は SECRETS_REF_IGNORED_INACTIVE_SURFACE コードで非致命的な診断を出力します。

非アクティブなサーフェスの例:

  • 無効化されたチャネル/アカウントエントリ。
  • 有効なアカウントが継承しないトップレベルのチャネルクレデンシャル。
  • 無効化されたツール/機能のサーフェス。
  • tools.web.search.provider で選択されていない Web 検索プロバイダー固有のキー。 自動モード(プロバイダー未設定)では、プロバイダー自動検出のために優先順位に基づいてキーが参照されます。 選択後、選択されなかったプロバイダーのキーは選択されるまで非アクティブとして扱われます。
  • gateway.remote.token / gateway.remote.password の SecretRef は以下のいずれかが true の場合にアクティブです:
    • gateway.mode=remote
    • gateway.remote.url が設定されている
    • gateway.tailscale.modeserve または funnel
    • ローカルモードでそれらのリモートサーフェスがない場合:
      • gateway.remote.token はトークン認証が優先され、env/auth トークンが設定されていない場合にアクティブ。
      • gateway.remote.password はパスワード認証が優先され、env/auth パスワードが設定されていない場合にのみアクティブ。
  • gateway.auth.token の SecretRef は、OPENCLAW_GATEWAY_TOKEN(または CLAWDBOT_GATEWAY_TOKEN)が設定されている場合、起動時の認証解決では非アクティブです(env トークン入力がそのランタイムで優先されるため)。

Gateway 認証サーフェスの診断

gateway.auth.tokengateway.auth.passwordgateway.remote.tokengateway.remote.password に SecretRef が設定されている場合、Gateway の起動/リロード時にサーフェスの状態が明示的にログ出力されます:

  • active:SecretRef は有効な認証サーフェスの一部であり、解決が必要。
  • inactive:別の認証サーフェスが優先するか、リモート認証が無効/非アクティブなため、このランタイムでは無視。

これらのエントリは SECRETS_GATEWAY_AUTH_SURFACE でログ出力され、アクティブサーフェスポリシーで使用された理由が含まれるため、クレデンシャルがアクティブまたは非アクティブとして扱われた理由を確認できます。

オンボーディングのリファレンスプリフライト

オンボーディングが対話モードで実行され、SecretRef ストレージを選択した場合、OpenClaw は保存前にプリフライト検証を実行します:

  • env ref:env 変数名を検証し、オンボーディング中に空でない値が見えることを確認。
  • プロバイダー ref(file または exec):プロバイダー選択を検証し、id を解決し、解決された値の型を確認。
  • クイックスタート再利用パス:gateway.auth.token が既に SecretRef の場合、オンボーディングは probe/ダッシュボードブートストラップの前にそれを解決します(envfileexec ref に対して同じフェイルファストゲートを使用)。

検証が失敗した場合、オンボーディングはエラーを表示してリトライできます。

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

env プロバイダー

  • allowlist によるオプションの許可リスト。
  • 欠損/空の env 値は解決失敗になります。

file プロバイダー

  • path からローカルファイルを読み取ります。
  • mode: "json" は JSON オブジェクトペイロードを期待し、id をポインターとして解決します。
  • mode: "singleValue" は ref id "value" を期待し、ファイルの内容を返します。
  • パスは所有権/権限チェックに合格する必要があります。
  • Windows のフェイルクローズドに関する注意:パスに対する ACL 検証が利用できない場合、解決は失敗します。信頼できるパスに限り、そのプロバイダーで allowInsecurePath: true を設定してパスセキュリティチェックをバイパスできます。

exec プロバイダー

  • 設定された絶対バイナリパスを実行します(シェルなし)。
  • デフォルトでは command は通常ファイル(シンボリックリンクではない)を指す必要があります。
  • allowSymlinkCommand: true を設定するとシンボリックリンクのコマンドパスを許可できます(例:Homebrew shim)。OpenClaw は解決されたターゲットパスを検証します。
  • allowSymlinkCommandtrustedDirs を組み合わせてパッケージマネージャーのパスに使用します(例:["/opt/homebrew"])。
  • タイムアウト、無出力タイムアウト、出力バイト制限、env 許可リスト、信頼ディレクトリをサポートします。
  • 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, // 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" },
      },
    },
  },
}

サポート対象のクレデンシャルサーフェス

正規のサポート対象/非サポートクレデンシャルは以下に記載されています:

ランタイムで生成またはローテーションされるクレデンシャルと OAuth リフレッシュマテリアルは、読み取り専用の SecretRef 解決から意図的に除外されています。

必須動作と優先順位

  • ref なしのフィールド:変更なし。
  • ref ありのフィールド:アクティベーション中のアクティブサーフェスで必須。
  • 平文と ref の両方が存在する場合、サポート対象の優先順位パスでは ref が優先。

警告および監査シグナル:

  • SECRETS_REF_OVERRIDES_PLAINTEXT(ランタイム警告)
  • REF_SHADOWEDauth-profiles.json のクレデンシャルが openclaw.json の ref より優先される場合の監査結果)

Google Chat の互換性動作:

  • serviceAccountRef が平文の serviceAccount よりも優先。
  • 兄弟の ref が設定されている場合、平文の値は無視されます。

アクティベーショントリガー

シークレットのアクティベーションは以下で実行されます:

  • 起動(プリフライト + 最終アクティベーション)
  • 設定リロードのホットアプライパス
  • 設定リロードの再起動チェックパス
  • secrets.reload による手動リロード

アクティベーションコントラクト:

  • 成功するとスナップショットをアトミックにスワップ。
  • 起動失敗は Gateway の起動を中止。
  • ランタイムリロード失敗は最後の正常なスナップショットを維持。
  • アウトバウンドヘルパー/ツール呼び出しへの明示的なチャネルトークン提供は SecretRef アクティベーションをトリガーしません。アクティベーションポイントは起動、リロード、明示的な secrets.reload のみです。

劣化と回復シグナル

正常状態の後にリロード時のアクティベーションが失敗すると、OpenClaw はシークレット劣化状態に入ります。

ワンショットシステムイベントおよびログコード:

  • SECRETS_RELOADER_DEGRADED
  • SECRETS_RELOADER_RECOVERED

動作:

  • 劣化:ランタイムは最後の正常なスナップショットを維持。
  • 回復:次の成功したアクティベーション後に1回発行。
  • 既に劣化状態での繰り返し失敗は警告をログ出力しますが、イベントを連発しません。
  • 起動時のフェイルファストはランタイムがアクティブにならなかったため劣化イベントを発行しません。

コマンドパス解決

コマンドパスは Gateway スナップショット RPC 経由でサポート対象の SecretRef 解決にオプトインできます。

大きく2つの動作があります:

  • 厳密なコマンドパス(例:openclaw memory のリモートメモリパスや openclaw qr --remote)はアクティブスナップショットから読み取り、必要な SecretRef が利用できない場合は即座に失敗します。
  • 読み取り専用コマンドパス(例:openclaw statusopenclaw status --allopenclaw channels statusopenclaw channels resolve、読み取り専用の doctor/config 修復フロー)もアクティブスナップショットを優先しますが、そのコマンドパスで対象の SecretRef が利用できない場合は中止ではなく劣化します。

読み取り専用の動作:

  • Gateway が実行中の場合、これらのコマンドはまずアクティブスナップショットから読み取ります。
  • Gateway の解決が不完全または Gateway が利用不可の場合、特定のコマンドサーフェスに対してターゲットを絞ったローカルフォールバックを試みます。
  • ターゲットの SecretRef が依然として利用不可の場合、コマンドは劣化した読み取り専用出力と明示的な診断(「設定されているがこのコマンドパスでは利用不可」など)を伴って続行します。
  • この劣化動作はコマンドローカルのみです。ランタイムの起動、リロード、送信/認証パスを弱めることはありません。

その他の注意事項:

  • バックエンドのシークレットローテーション後のスナップショット更新は openclaw secrets reload で処理されます。
  • これらのコマンドパスが使用する Gateway 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 エントリ内の平文の機密プロバイダーヘッダー残留
  • 未解決の ref
  • 優先順位のシャドウイング(auth-profiles.jsonopenclaw.json の ref より優先)
  • レガシー残留(auth.json、OAuth リマインダー)

ヘッダー残留に関する注意:

  • 機密プロバイダーヘッダーの検出は名前ヒューリスティックベースです(authorizationx-api-keytokensecretpasswordcredential などの一般的な認証/クレデンシャルヘッダー名とフラグメント)。

secrets configure

対話的ヘルパーで以下を行います:

  • まず secrets.providers を設定(env/file/exec、追加/編集/削除)
  • openclaw.json 内のサポート対象のシークレット保持フィールドと、1つのエージェントスコープの 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 ユニオンは、フォームモードよりもローエディタモードの方が設定しやすい場合があります。

関連ドキュメント