シークレット管理
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=remotegateway.remote.urlが設定されているgateway.tailscale.modeがserveまたは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.token、gateway.auth.password、gateway.remote.token、gateway.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/ダッシュボードブートストラップの前にそれを解決します(env、file、execref に対して同じフェイルファストゲートを使用)。
検証が失敗した場合、オンボーディングはエラーを表示してリトライできます。
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 は解決されたターゲットパスを検証します。allowSymlinkCommandとtrustedDirsを組み合わせてパッケージマネージャーのパスに使用します(例:["/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_SHADOWED(auth-profiles.jsonのクレデンシャルがopenclaw.jsonの ref より優先される場合の監査結果)
Google Chat の互換性動作:
serviceAccountRefが平文のserviceAccountよりも優先。- 兄弟の ref が設定されている場合、平文の値は無視されます。
アクティベーショントリガー
シークレットのアクティベーションは以下で実行されます:
- 起動(プリフライト + 最終アクティベーション)
- 設定リロードのホットアプライパス
- 設定リロードの再起動チェックパス
secrets.reloadによる手動リロード
アクティベーションコントラクト:
- 成功するとスナップショットをアトミックにスワップ。
- 起動失敗は Gateway の起動を中止。
- ランタイムリロード失敗は最後の正常なスナップショットを維持。
- アウトバウンドヘルパー/ツール呼び出しへの明示的なチャネルトークン提供は SecretRef アクティベーションをトリガーしません。アクティベーションポイントは起動、リロード、明示的な
secrets.reloadのみです。
劣化と回復シグナル
正常状態の後にリロード時のアクティベーションが失敗すると、OpenClaw はシークレット劣化状態に入ります。
ワンショットシステムイベントおよびログコード:
SECRETS_RELOADER_DEGRADEDSECRETS_RELOADER_RECOVERED
動作:
- 劣化:ランタイムは最後の正常なスナップショットを維持。
- 回復:次の成功したアクティベーション後に1回発行。
- 既に劣化状態での繰り返し失敗は警告をログ出力しますが、イベントを連発しません。
- 起動時のフェイルファストはランタイムがアクティブにならなかったため劣化イベントを発行しません。
コマンドパス解決
コマンドパスは Gateway スナップショット RPC 経由でサポート対象の SecretRef 解決にオプトインできます。
大きく2つの動作があります:
- 厳密なコマンドパス(例:
openclaw memoryのリモートメモリパスやopenclaw qr --remote)はアクティブスナップショットから読み取り、必要な SecretRef が利用できない場合は即座に失敗します。 - 読み取り専用コマンドパス(例:
openclaw status、openclaw status --all、openclaw channels status、openclaw 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.json、auth-profiles.json、.env、生成されたagents/*/agent/models.json) - 生成された
models.jsonエントリ内の平文の機密プロバイダーヘッダー残留 - 未解決の ref
- 優先順位のシャドウイング(
auth-profiles.jsonがopenclaw.jsonの ref より優先) - レガシー残留(
auth.json、OAuth リマインダー)
ヘッダー残留に関する注意:
- 機密プロバイダーヘッダーの検出は名前ヒューリスティックベースです(
authorization、x-api-key、token、secret、password、credentialなどの一般的な認証/クレデンシャルヘッダー名とフラグメント)。
secrets configure
対話的ヘルパーで以下を行います:
- まず
secrets.providersを設定(env/file/exec、追加/編集/削除) openclaw.json内のサポート対象のシークレット保持フィールドと、1つのエージェントスコープのauth-profiles.jsonを選択- ターゲットピッカーから直接新しい
auth-profiles.jsonマッピングを作成可能 - SecretRef の詳細をキャプチャ(
source、provider、id) - プリフライト解決を実行
- 即座に適用可能
便利なモード:
openclaw secrets configure --providers-onlyopenclaw secrets configure --skip-provider-setupopenclaw 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 ユニオンは、フォームモードよりもローエディタモードの方が設定しやすい場合があります。
関連ドキュメント
- CLI コマンド:secrets
- プランコントラクトの詳細:Secrets Apply プランコントラクト
- クレデンシャルサーフェス:SecretRef クレデンシャルサーフェス
- 認証セットアップ:認証
- セキュリティ態勢:セキュリティ
- 環境変数の優先順位:環境変数