Exec 承認
Exec 承認は、サンドボックス化されたエージェントが実ホスト(gateway または node)でコマンドを実行するためのコンパニオンアプリ / ノードホストのガードレールです。安全インターロックのようなもので、ポリシー+アローリスト+(任意の)ユーザー承認がすべて合意した場合にのみコマンドが許可されます。
Exec 承認はツールポリシーと elevated ゲーティングに追加されるものです(elevated が full に設定されている場合は承認をスキップ)。
有効なポリシーは tools.exec.* と承認デフォルトの厳しい方です。承認フィールドが省略された場合は tools.exec の値が使用されます。
コンパニオンアプリの UI が利用できない場合、プロンプトを必要とするリクエストは ask フォールバック(デフォルト: deny)で解決されます。
適用箇所
Exec 承認は実行ホスト上でローカルに実施されます:
- Gateway ホスト → Gateway マシン上の
openclawプロセス - ノードホスト → ノードランナー(macOS コンパニオンアプリまたはヘッドレスノードホスト)
信頼モデルの補足:
- Gateway 認証済みの呼び出し元は、その Gateway の信頼されたオペレーターです。
- ペアリング済みノードは、その信頼されたオペレーター機能をノードホストに拡張します。
- Exec 承認は意図しない実行のリスクを低減しますが、ユーザー単位の認証境界ではありません。
- 承認済みノードホスト実行は正規の実行コンテキストをバインドします: 正規の cwd、正確な argv、存在する場合は env バインディング、該当する場合はピン留めされた実行パス。
- シェルスクリプトおよび直接インタープリタ/ランタイムファイル呼び出しでは、OpenClaw は 1 つの具体的なローカルファイルオペランドのバインドも試みます。承認後・実行前にそのバインドファイルが変更された場合、変更されたコンテンツの実行ではなく拒否されます。
- このファイルバインディングは意図的にベストエフォートであり、すべてのインタープリタ/ランタイムローダーパスの完全なセマンティックモデルではありません。承認モードがバインド対象として正確に 1 つの具体的なローカルファイルを特定できない場合、完全なカバレッジを偽装する代わりに承認ベース実行を拒否します。
macOS での分割:
- ノードホストサービス は、ローカル IPC を介して macOS アプリ に
system.runを転送。 - macOS アプリ が承認を実施し、UI コンテキストでコマンドを実行。
設定とストレージ
承認は実行ホスト上のローカル JSON ファイルに保存されます:
~/.openclaw/exec-approvals.json
スキーマ例:
{
"version": 1,
"socket": {
"path": "~/.openclaw/exec-approvals.sock",
"token": "base64url-token"
},
"defaults": {
"security": "deny",
"ask": "on-miss",
"askFallback": "deny",
"autoAllowSkills": false
},
"agents": {
"main": {
"security": "allowlist",
"ask": "on-miss",
"askFallback": "deny",
"autoAllowSkills": true,
"allowlist": [
{
"id": "B0C8C0B3-2C2D-4F8A-9A3C-5A4B3C2D1E0F",
"pattern": "~/Projects/**/bin/rg",
"lastUsedAt": 1737150000000,
"lastUsedCommand": "rg -n TODO",
"lastResolvedPath": "/Users/user/Projects/.../bin/rg"
}
]
}
}
}
ポリシー設定
Security(exec.security)
- deny: すべてのホスト exec リクエストをブロック。
- allowlist: アローリストに登録されたコマンドのみ許可。
- full: すべてを許可(elevated と同等)。
Ask(exec.ask)
- off: プロンプトなし。
- on-miss: アローリストに一致しない場合のみプロンプト。
- always: 毎回プロンプト。
Ask フォールバック(askFallback)
プロンプトが必要だが UI に到達できない場合のフォールバック:
- deny: ブロック。
- allowlist: アローリストに一致する場合のみ許可。
- full: 許可。
アローリスト(エージェント単位)
アローリストはエージェント単位です。複数のエージェントがある場合は、macOS アプリで編集対象のエージェントを切り替えてください。パターンは大文字小文字を区別しない glob マッチです。パターンはバイナリパスに解決される必要があります(basename のみのエントリは無視されます)。レガシーの agents.default エントリはロード時に agents.main に移行されます。
例:
~/Projects/**/bin/peekaboo~/.local/bin/*/opt/homebrew/bin/rg
各アローリストエントリは以下を追跡:
- id UI 識別用の安定した UUID(任意)
- last used タイムスタンプ
- last used command
- last resolved path
スキル CLI の自動許可
スキル CLI の自動許可が有効な場合、既知のスキルが参照する実行ファイルはノード(macOS ノードまたはヘッドレスノードホスト)でアローリスト登録済みとして扱われます。これは Gateway RPC 経由の skills.bins を使用してスキルバイナリリストを取得します。厳密な手動アローリストが必要な場合は無効にしてください。
信頼に関する重要な注意:
- これは手動パスアローリストエントリとは別の暗黙的な便利なアローリストです。
- Gateway とノードが同じ信頼境界内にある信頼されたオペレーター環境向けです。
- 厳密な明示的信頼が必要な場合は、
autoAllowSkills: falseのままにし、手動パスアローリストエントリのみ使用してください。
安全バイナリ(stdin 専用)
tools.exec.safeBins は、アローリストモードで明示的なアローリストエントリなしで実行できる小さな stdin 専用バイナリリスト(例: jq)を定義します。安全バイナリは位置引数としてのファイル引数やパスのようなトークンを拒否するため、入力ストリームに対してのみ操作可能です。ストリームフィルタ用の狭いファストパスとして扱い、汎用の信頼リストとしては使わないでください。
インタープリタやランタイムバイナリ(例: python3、node、ruby、bash、sh、zsh)を safeBins に追加しないでください。コマンドがコードを評価、サブコマンドを実行、ファイルを読み取る設計の場合は、明示的なアローリストエントリを使用し、承認プロンプトを有効にしてください。
カスタム安全バイナリには tools.exec.safeBinProfiles.<bin> で明示的なプロファイルを定義する必要があります。
バリデーションは argv の形状のみから決定論的に行われ(ホストファイルシステムの存在チェックなし)、許可/拒否の差異からファイル存在のオラクル動作を防止します。
デフォルトの安全バイナリではファイル指向オプションが拒否されます(例: sort -o、sort --output、sort --files0-from、sort --compress-program、sort --random-source、sort --temporary-directory/-T、wc --files0-from、jq -f/--from-file、grep -f/--file)。
安全バイナリは、stdin 専用の動作を破壊するオプションに対してバイナリごとの明示的なフラグポリシーも適用します(例: sort -o/--output/--compress-program や grep の再帰フラグ)。
安全バイナリモードでの長いオプションはフェイルクローズドでバリデーションされます: 不明なフラグや曖昧な省略形は拒否されます。
安全バイナリプロファイルで拒否されるフラグ:
grep:--dereference-recursive,--directories,--exclude-from,--file,--recursive,-R,-d,-f,-rjq:--argfile,--from-file,--library-path,--rawfile,--slurpfile,-L,-fsort:--compress-program,--files0-from,--output,--random-source,--temporary-directory,-T,-owc:--files0-from
安全バイナリは実行時に argv トークンをリテラルテキストとして扱うことも強制します(stdin 専用セグメントではグロブ展開も $VARS 展開もなし)。* や $HOME/... のようなパターンによるファイル読み取りの密輸を防止します。
安全バイナリは信頼されたバイナリディレクトリ(システムデフォルト + 任意の tools.exec.safeBinTrustedDirs)からの解決も必要です。PATH エントリは自動で信頼されません。
デフォルトの信頼済み安全バイナリディレクトリは意図的に最小限: /bin、/usr/bin。安全バイナリの実行ファイルがパッケージマネージャ/ユーザーパス(例: /opt/homebrew/bin、/usr/local/bin、/opt/local/bin、/snap/bin)にある場合は、tools.exec.safeBinTrustedDirs に明示的に追加してください。
アローリストモードではシェルチェインとリダイレクトは自動許可されません。
シェルチェイン(&&、||、;)は、すべてのトップレベルセグメントがアローリストを満たす場合(安全バイナリやスキル自動許可を含む)に許可されます。リダイレクトはアローリストモードでは未サポートです。
コマンド置換($() / バッククォート)はアローリスト解析中に拒否されます(ダブルクォート内を含む)。リテラルな $() テキストが必要な場合はシングルクォートを使用してください。
macOS コンパニオンアプリ承認では、シェル制御や展開構文(&&、||、;、|、`、$、<、>、(、))を含む生のシェルテキストは、シェルバイナリ自体がアローリスト登録されていない限りアローリストミスとして扱われます。
シェルラッパー(bash|sh|zsh ... -c/-lc)では、リクエストスコープの env オーバーライドは小さな明示的アローリストに縮小されます(TERM、LANG、LC_*、COLORTERM、NO_COLOR、FORCE_COLOR)。
アローリストモードでの always-allow 決定では、既知のディスパッチラッパー(env、nice、nohup、stdbuf、timeout)はラッパーパスではなく内部の実行ファイルパスを保持します。シェルマルチプレクサ(busybox、toybox)もシェルアプレット(sh、ash など)に対してアンラップされ、マルチプレクサバイナリではなく内部の実行ファイルが保持されます。ラッパーやマルチプレクサを安全にアンラップできない場合、アローリストエントリは自動的に保持されません。
デフォルトの安全バイナリ: jq、cut、uniq、head、tail、tr、wc。
grep と sort はデフォルトリストに含まれません。オプトインする場合は、非 stdin ワークフロー用の明示的なアローリストエントリを維持してください。
安全バイナリモードでの grep は -e/--regexp でパターンを指定してください。位置引数のパターン形式は、ファイルオペランドが曖昧な位置引数として密輸されないよう拒否されます。
安全バイナリ vs アローリスト
| 項目 | tools.exec.safeBins | アローリスト(exec-approvals.json) |
|---|---|---|
| 目的 | 狭い stdin フィルタの自動許可 | 特定の実行ファイルの明示的な信頼 |
| マッチタイプ | 実行ファイル名 + 安全バイナリ argv ポリシー | 解決済み実行ファイルパスの glob パターン |
| 引数スコープ | 安全バイナリプロファイルとリテラルトークンルールで制限 | パスマッチのみ。引数はユーザーの責任 |
| 典型例 | jq、head、tail、wc | python3、node、ffmpeg、カスタム CLI |
| 最適な用途 | パイプライン内の低リスクテキスト変換 | 広範な動作や副作用を持つツール |
設定の場所:
safeBinsは設定から取得(tools.exec.safeBinsまたはエージェント単位のagents.list[].tools.exec.safeBins)。safeBinTrustedDirsは設定から取得(tools.exec.safeBinTrustedDirsまたはエージェント単位のagents.list[].tools.exec.safeBinTrustedDirs)。safeBinProfilesは設定から取得(tools.exec.safeBinProfilesまたはエージェント単位のagents.list[].tools.exec.safeBinProfiles)。エージェント単位のプロファイルキーはグローバルキーをオーバーライド。- アローリストエントリはホストローカルの
~/.openclaw/exec-approvals.jsonのagents.<id>.allowlistに保存(またはコントロール UI /openclaw approvals allowlist ...経由)。 openclaw security auditは、インタープリタ/ランタイムバイナリがsafeBinsにあり明示的プロファイルがない場合にtools.exec.safe_bins_interpreter_unprofiledで警告。openclaw doctor --fixは欠落しているカスタムsafeBinProfiles.<bin>エントリを{}としてスキャフォールド可能(その後レビューして厳格化)。インタープリタ/ランタイムバイナリは自動スキャフォールドされません。
カスタムプロファイル例:
{
tools: {
exec: {
safeBins: ["jq", "myfilter"],
safeBinProfiles: {
myfilter: {
minPositional: 0,
maxPositional: 0,
allowedValueFlags: ["-n", "--limit"],
deniedFlags: ["-f", "--file", "-c", "--command"],
},
},
},
},
}
コントロール UI での編集
コントロール UI → Nodes → Exec approvals カードで、デフォルト、エージェント単位のオーバーライド、アローリストを編集できます。スコープ(Defaults またはエージェント)を選択し、ポリシーを調整し、アローリストパターンを追加/削除して保存します。UI にはパターンごとの最終使用メタデータが表示されるため、リストを整理しやすくなっています。
ターゲットセレクターは Gateway(ローカル承認)または Node を選択します。ノードは system.execApprovals.get/set をアドバタイズする必要があります(macOS アプリまたはヘッドレスノードホスト)。ノードがまだ exec 承認をアドバタイズしていない場合は、ローカルの ~/.openclaw/exec-approvals.json を直接編集してください。
CLI: openclaw approvals は Gateway またはノードの編集をサポート(承認 CLI を参照)。
承認フロー
プロンプトが必要な場合、Gateway はオペレータークライアントに exec.approval.requested をブロードキャストします。コントロール UI と macOS アプリが exec.approval.resolve で解決し、Gateway が承認されたリクエストをノードホストに転送します。
host=node の場合、承認リクエストには正規の systemRunPlan ペイロードが含まれます。Gateway は承認済み system.run リクエストの転送時に、そのプランをコマンド/cwd/セッションコンテキストの権威あるソースとして使用します。
インタープリタ/ランタイムコマンド
承認ベースのインタープリタ/ランタイム実行は意図的に保守的です:
- 正確な argv/cwd/env コンテキストが常にバインドされる。
- 直接シェルスクリプトおよび直接ランタイムファイル形式は、1 つの具体的なローカルファイルスナップショットにベストエフォートでバインド。
- 1 つの直接ローカルファイルに解決される一般的なパッケージマネージャラッパー形式(例:
pnpm exec、pnpm node、npm exec、npx)はバインド前にアンラップ。 - OpenClaw がインタープリタ/ランタイムコマンドで正確に 1 つの具体的なローカルファイルを特定できない場合(例: パッケージスクリプト、eval 形式、ランタイム固有のローダーチェーン、曖昧な複数ファイル形式)、持っていないセマンティックカバレッジを主張する代わりに承認ベース実行を拒否。
- そのようなワークフローでは、サンドボックス化、別のホスト境界、またはオペレーターがより広範なランタイムセマンティクスを受け入れる明示的な信頼済みアローリスト/full ワークフローを推奨。
承認が必要な場合、exec ツールは承認 ID 付きで即座に返します。その ID を使って後続のシステムイベント(Exec finished / Exec denied)と相関させてください。タイムアウト前に決定が届かない場合、リクエストは承認タイムアウトとして扱われ、拒否理由として表示されます。
確認ダイアログには以下が含まれます:
- コマンド + 引数
- cwd
- エージェント ID
- 解決済み実行パス
- ホスト + ポリシーメタデータ
アクション:
- Allow once → 今回のみ実行
- Always allow → アローリストに追加して実行
- Deny → ブロック
チャットチャンネルへの承認転送
exec 承認プロンプトを任意のチャットチャンネル(プラグインチャンネルを含む)に転送し、/approve で承認できます。通常のアウトバウンド配信パイプラインを使用します。
設定:
{
approvals: {
exec: {
enabled: true,
mode: "session", // "session" | "targets" | "both"
agentFilter: ["main"],
sessionFilter: ["discord"], // 部分文字列または正規表現
targets: [
{ channel: "slack", to: "U12345678" },
{ channel: "telegram", to: "123456789" },
],
},
},
}
チャットでの返信:
/approve <id> allow-once
/approve <id> allow-always
/approve <id> deny
組み込みチャット承認クライアント
Discord と Telegram はチャンネル固有の設定による明示的な exec 承認クライアントとしても機能します。
- Discord:
channels.discord.execApprovals.* - Telegram:
channels.telegram.execApprovals.*
これらのクライアントはオプトインです。チャンネルで exec 承認が有効になっていない場合、OpenClaw はそのチャンネルで会話が行われたというだけで承認サーフェスとして扱いません。
共通の動作:
- 設定された承認者のみが承認または拒否可能
- リクエスターが承認者である必要はない
- チャンネル配信が有効な場合、承認プロンプトにコマンドテキストを含む
- オペレーター UI も設定された承認クライアントもリクエストを受け付けられない場合、プロンプトは
askFallbackにフォールバック
Telegram はデフォルトで承認者の DM に配信(target: "dm")。承認プロンプトを発信元の Telegram チャット/トピックにも表示したい場合は channel または both に切り替え可能。Telegram フォーラムトピックでは、OpenClaw は承認プロンプトと承認後のフォローアップにトピックを保持します。
参照:
macOS IPC フロー
Gateway -> Node Service (WS)
| IPC (UDS + token + HMAC + TTL)
v
Mac App (UI + approvals + system.run)
セキュリティ補足:
- Unix ソケットモード
0600、トークンはexec-approvals.jsonに保存。 - 同一 UID ピアチェック。
- チャレンジ/レスポンス(nonce + HMAC トークン + リクエストハッシュ)+ 短い TTL。
システムイベント
Exec のライフサイクルはシステムメッセージとして表示されます:
Exec running(コマンドが実行通知閾値を超えた場合のみ)Exec finishedExec denied
これらはノードがイベントを報告した後、エージェントのセッションにポストされます。
Gateway ホストの exec 承認は、コマンド終了時に同じライフサイクルイベントを発行します(閾値を超えて実行中の場合は任意で通知)。
承認ゲート付き exec は、相関のために承認 ID を runId として再利用します。
留意事項
- full は強力です。可能な限りアローリストを推奨。
- ask は迅速な承認を可能にしつつ、オペレーターを関与させ続けます。
- エージェント単位のアローリストにより、あるエージェントの承認が他のエージェントに漏洩することを防止。
- 承認は認可済み送信者からのホスト exec リクエストにのみ適用。未認可の送信者は
/execを発行できません。 /exec security=fullは認可済みオペレーター向けのセッションレベルの便利機能で、設計上承認をスキップ。ホスト exec を完全にブロックするには、承認セキュリティをdenyに設定するか、ツールポリシーでexecツールを拒否。
関連: