Tools
実行承認 — 高度な設定
高度な exec 承認のトピック:safeBins の高速パス、インタープリター/ランタイムの
バインディング、チャットチャネルへの承認転送(ネイティブ配信を含む)。
中核となるポリシーと承認フローについては、Exec 承認を参照してください。
セーフバイナリ(stdin のみ)
tools.exec.safeBins は、明示的な許可リストエントリなしで
許可リストモードで実行できる、stdin のみを扱うバイナリ(例:cut)を指定します。
セーフバイナリは位置引数のファイル引数とパス形式のトークンを拒否するため、
入力ストリームのみを操作できます。これは一般的な信頼リストではなく、
ストリームフィルター向けの限定的な高速パスとして扱ってください。
デフォルトのセーフバイナリ:
cut、uniq、head、tail、tr、wc
grep と sort はデフォルトリストに含まれていません。オプトインする場合は、
stdin 以外を扱うワークフロー用に明示的な許可リストエントリを維持してください。
セーフバイナリモードで grep を使用する場合は、パターンを -e/--regexp で指定してください。
位置引数形式のパターンは拒否されるため、曖昧な位置引数としてファイルオペランドを
紛れ込ませることはできません。
Argv の検証と拒否されるフラグ
検証は argv の形状のみから決定論的に行われます(ホストファイルシステム上の存在確認は
行いません)。これにより、許可/拒否の差異を利用したファイル存在オラクルの動作を防ぎます。
デフォルトのセーフバイナリでは、ファイル指向のオプションが拒否されます。長いオプションは
フェイルクローズで検証されます(不明なフラグと曖昧な省略形は拒否されます)。
デフォルトバイナリで認識される読み取り専用のブールフラグ(例:wc -l、tr -d、
uniq -c)は受け入れられますが、認識されない短いフラグはフェイルクローズのままとなり、
手動承認にフォールスルーします。
セーフバイナリプロファイル別の拒否フラグ:
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、-otail:--follow、--retry、-F、-fwc:--files0-from
セーフバイナリでは、stdin のみを扱うセグメントについて、実行時に argv トークンを
リテラルテキストとして扱うことも強制されます(グロブ展開も $VARS 展開も行いません)。
そのため、* や $HOME/... のようなパターンを使用してファイル読み取りを
紛れ込ませることはできません。awk、sed、jq は、そのセマンティクスを stdin のみに
限定して検証できないため、常にセーフバイナリとして拒否されます。jq は環境データを
読み取り、モジュールや起動ファイルから jq コードを読み込めます。これらのツールでは、
safeBins の代わりに明示的な許可リストエントリまたは承認プロンプトを使用してください。
信頼済みバイナリディレクトリ
セーフバイナリは、信頼済みバイナリディレクトリ(システムのデフォルトに加え、
オプションの tools.exec.safeBinTrustedDirs)から解決される必要があります。
PATH のエントリが自動的に信頼されることはありません。デフォルトの信頼済みディレクトリは、
意図的に最小限の /bin、/usr/bin に限定されています。セーフバイナリの実行ファイルが
パッケージマネージャー/ユーザー用パス(例:/opt/homebrew/bin、/usr/local/bin、
/opt/local/bin、/snap/bin)にある場合は、それらを
tools.exec.safeBinTrustedDirs に明示的に追加してください。
シェルの連結、ラッパー、マルチプレクサー
シェルの連結(&&、||、;)は、トップレベルのすべてのセグメントが
許可リストを満たす場合(セーフバイナリまたは Skills の自動許可を含む)に許可されます。
リダイレクトは、許可リストモードでは引き続きサポートされません。コマンド置換
($()/バッククォート)は、二重引用符の内部を含め、許可リストの解析時に拒否されます。
リテラルの $() テキストが必要な場合は、単一引用符を使用してください。
macOS コンパニオンアプリでの承認では、シェル制御または展開構文(&&、||、;、|、
`, $、<、>、(、))を含む生のシェルテキストは、シェルバイナリ自体が
許可リストに含まれていない限り、許可リスト不一致として扱われます。
シェルラッパー(bash|sh|zsh ... -c/-lc)では、リクエストスコープの環境変数オーバーライドは、
小規模な明示的許可リスト(TERM、LANG、LC_*、COLORTERM、
NO_COLOR、FORCE_COLOR)に限定されます。
許可リストモードで allow-always を選択した場合、透過的なディスパッチラッパー
(例:env、flock、nice、nohup、stdbuf、timeout)では、ラッパーのパスではなく、
内側の実行ファイルのパスが永続化されます。シェルマルチプレクサー(busybox、toybox)も、
シェルアプレット(sh、ash など)について同じように展開されます。ラッパーまたは
マルチプレクサーを安全に展開できない場合、許可リストエントリは自動的に永続化されません。
python3 や node などのインタープリターを許可リストに追加する場合は、
インライン評価に引き続き明示的な承認を要求するため、tools.exec.strictInlineEval=true を
推奨します。厳格モードでも、allow-always は無害なインタープリター/スクリプト呼び出しを
永続化できますが、インライン評価を運ぶ呼び出しは自動的には永続化されません。
セーフバイナリと許可リストの比較
| トピック | tools.exec.safeBins |
許可リスト(exec-approvals.json) |
|---|---|---|
| 目的 | 限定的な stdin フィルターを自動許可 | 特定の実行ファイルを明示的に信頼 |
| 照合タイプ | 実行ファイル名 + セーフバイナリの argv ポリシー | 解決済み実行ファイルパスの glob、または PATH 経由で呼び出されるコマンド用の裸のコマンド名 glob |
| 引数の範囲 | セーフバイナリプロファイルとリテラルトークン規則によって制限 | デフォルトではパス照合。オプションの argPattern で解析済み argv を制限可能 |
| 代表例 | head、tail、tr、wc |
jq、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)から取得されます。エージェントごとのプロファイルキーはグローバルキーを上書きします。- 許可リストエントリは、ホストローカルの承認ファイル内の
agents.<id>.allowlistに保存されます(または Control UI/openclaw approvals allowlist ...から設定します)。 - インタープリター/ランタイムのバイナリが明示的なプロファイルなしで
safeBinsに含まれている場合、openclaw security auditはtools.exec.safe_bins_interpreter_unprofiledで警告します。 openclaw doctor --fixは、不足しているカスタムsafeBinProfiles.<bin>エントリを{}として生成できます(その後、確認して制約を強化してください)。インタープリター/ランタイムのバイナリは自動生成されません。
カスタムプロファイルの例: OC_I18N_900000
インタープリター/ランタイムコマンド
承認に基づくインタープリター/ランタイムの実行は、意図的に保守的です。
- argv/cwd/env の正確なコンテキストが常にバインドされます。
- シェルスクリプトの直接実行形式とランタイムファイルの直接実行形式は、ベストエフォートで単一の具体的なローカルファイルのスナップショットにバインドされます。
- 単一の直接的なローカルファイルに解決される一般的なパッケージマネージャーのラッパー形式(例:
pnpm exec、pnpm node、npm exec、npx)は、バインド前に展開されます。 - OpenClaw がインタープリター/ランタイムコマンドについて具体的なローカルファイルを正確に 1 つ特定できない場合(例:パッケージスクリプト、評価形式、ランタイム固有のローダーチェーン、曖昧な複数ファイル形式)、提供できないセマンティックな範囲を保証する代わりに、承認に基づく実行を拒否します。
- そのようなワークフローでは、サンドボックス化、別のホスト境界、またはオペレーターがより広範なランタイムセマンティクスを受け入れる明示的な信頼済み許可リスト/完全なワークフローを推奨します。
承認が必要な場合、exec ツールは承認 ID とともに直ちに返ります。その ID を使用して、
後続の承認済み実行システムイベント(Exec finished、設定されている場合は Exec running)を
関連付けてください。タイムアウトまでに判断が届かない場合、リクエストは承認タイムアウトとして
扱われ、最終的なホストコマンド拒否として通知されます。元のセッションがあるメインエージェントの
非同期承認では、OpenClaw は内部フォローアップによってそのセッションも再開するため、
エージェントは後から結果の欠落を修復するのではなく、コマンドが実行されなかったことを認識できます。
保留中の exec 承認は、デフォルトで 30 分後に期限切れになります。
フォローアップ配信の動作
承認された非同期 exec が完了すると、OpenClaw は同じセッションにフォローアップの agent ターンを
送信します。拒否された非同期承認でも、拒否ステータスには同じメインセッションのフォローアップ経路を
使用しますが、昇格されたランタイムの引き継ぎは登録されず、コマンドも実行されません。再開可能な
メインセッションがない拒否は、抑制されるか、安全な直接経路が存在する場合はそこから報告されます。
- 有効な外部配信先(配信可能なチャネルと送信先
to)が存在する場合、フォローアップ配信はそのチャネルを使用します。 - 外部配信先のない Web チャットのみのフローまたは内部セッションフローでは、フォローアップ配信はセッション内のみに留まります(
deliver: false)。 - 呼び出し元が厳格な外部配信を明示的に要求し、解決可能な外部チャネルがない場合、リクエストは
INVALID_REQUESTで失敗します。 bestEffortDeliverが有効で、外部チャネルを解決できない場合、配信は失敗せず、セッション内のみにダウングレードされます。
チャットチャネルへの承認転送
exec 承認プロンプトは、任意のチャットチャネル(Plugin チャネルを含む)に転送し、
/approve で承認できます。これは通常の送信配信パイプラインを使用します。
設定:
OC_I18N_900001
チャットで返信:
OC_I18N_900002
/approve コマンドは、exec 承認と Plugin 承認の両方を処理します。ID が保留中の exec 承認に
一致しない場合は、代わりに Plugin 承認を自動的に確認します。このフォールバックは
「承認が見つからない」失敗に限定されます。実際の exec 承認の拒否/エラーに対して、
暗黙に Plugin 承認として再試行することはありません。
Plugin 承認の転送
Plugin 承認の転送は exec 承認と同じ配信パイプラインを使用しますが、
approvals.plugin に独立した設定があります。一方を有効または無効にしても、もう一方には
影響しません。Plugin 作成時の動作、リクエストフィールド、判断のセマンティクスについては、
Plugin 権限リクエストを参照してください。
OC_I18N_900003
設定の構造は approvals.exec と同一で、enabled、mode、agentFilter、
sessionFilter、targets は同じように動作します。
共有インタラクティブ返信をサポートするチャンネルでは、exec 承認と
Plugin 承認の両方に同じ承認ボタンが表示されます。共有インタラクティブ UI がないチャンネルでは、/approve
の手順を含むプレーンテキストにフォールバックします。Plugin 承認リクエストでは、利用可能な判断が制限される場合があります。承認画面では
リクエストで宣言された判断セットを使用し、提示されていない判断を送信しようとすると
Gateway が拒否します。
任意のチャンネルでの同一チャット承認
exec または Plugin の承認リクエストが配信可能なチャット画面から発生した場合、デフォルトでは同じチャットで
/approve を使用して承認できます。これは既存の Web UI とターミナル UI のフローに加えて、Slack、Matrix、Microsoft Teams、
および同様の配信可能なチャットに適用され、その会話の通常のチャンネル認証モデルを使用します。発生元のチャットがすでにコマンドを送信し、
返信を受信できる場合、承認リクエストを保留状態にしておくためだけに別個のネイティブ配信アダプターは
不要になります。
Discord、Telegram、QQ bot も同一チャットでの /approve をサポートしますが、これらのチャンネルでは、ネイティブ承認配信が無効な場合でも、
認可に解決済みの承認者リストを引き続き使用します。
ネイティブ承認配信
一部のチャンネルはネイティブ承認クライアントとしても機能できます。対象は Discord、Slack、Telegram、Matrix、QQ bot です。
ネイティブクライアントは、共有の同一チャット /approve フローに加えて、承認者への DM、発生元チャットへのファンアウト、
チャンネル固有のインタラクティブな承認 UX を提供します。
ネイティブ承認カードまたはボタンが利用可能な場合、そのネイティブ UI がエージェント向けの主要な経路になります。
ツールの結果でチャット承認が利用できない、または手動承認が唯一残された経路であると示されない限り、エージェントは
重複するプレーンチャットの /approve コマンドを追加で表示すべきではありません。
ネイティブ承認クライアントが設定されていても、発生元チャンネルでネイティブランタイムがアクティブでない場合、
OpenClaw はローカルの決定論的な /approve プロンプトを表示したままにします。ネイティブランタイムが
アクティブで配信を試みたものの、どの宛先にもカードが届かなかった場合、OpenClaw はリクエストを引き続き解決できるように、
正確な /approve <id> <decision> コマンドを含む同一チャットのフォールバック通知を送信します。
一般モデル:
- exec 承認が必要かどうかは、引き続きホストの exec ポリシーが決定します
approvals.execは、承認プロンプトを他のチャット宛先へ転送する処理を制御しますchannels.<channel>.execApprovalsは、Discord、Slack、Telegram、QQ bot、および同様の チャンネル固有ネイティブクライアントを有効にするかどうかを制御します- リクエストが Slack から発生し、Slack Plugin 承認者を解決できる場合、Slack Plugin 承認では Slack のネイティブ承認クライアントを使用できます。
また、Slack の exec 承認が無効な場合でも、
approvals.pluginで Plugin 承認を Slack の セッションまたは宛先へルーティングできます - Google Chat のネイティブ承認カードは、
dm.allowFromまたはdefaultToから安定したusers/<id>承認者を解決できる場合、Google Chat のスペースまたはスレッドから発生した exec 承認と Plugin 承認を処理します。判断にはリアクションイベントを使用しません - WhatsApp と Signal のリアクション承認配信は、
approvals.execとapprovals.pluginによって制限されます。これらにはchannels.<channel>.execApprovalsブロックがありません
以下の条件をすべて満たす場合、ネイティブ承認クライアントでは DM 優先配信が自動的に有効になります:
- チャンネルがネイティブ承認配信をサポートしている
- 明示的な
execApprovals.approvers、またはcommands.ownerAllowFromなどのオーナー ID から承認者を解決できる channels.<channel>.execApprovals.enabledが未設定、または"auto"である
ネイティブ承認クライアントを明示的に無効にするには、enabled: false を設定します。承認者を解決できる場合に強制的に
有効にするには、enabled: true を設定します。公開される発生元チャットへの配信は、引き続き
channels.<channel>.execApprovals.target で明示的に指定します。ネイティブの target で発生元チャットへの配信を有効にすると、
承認プロンプトにコマンドテキストが含まれます。
FAQ: チャット承認に exec 承認設定が 2 つあるのはなぜですか?
- Discord:
channels.discord.execApprovals.* - Slack:
channels.slack.execApprovals.* - Telegram:
channels.telegram.execApprovals.* - QQ bot:
channels.qqbot.execApprovals.* - Google Chat: 安定した承認者を
channels.googlechat.dm.allowFromまたはchannels.googlechat.defaultToで設定します。execApprovalsブロックは不要です - WhatsApp:
approvals.execとapprovals.pluginを使用して、承認プロンプトを WhatsApp にルーティングします - Signal:
approvals.execとapprovals.pluginを使用して、承認プロンプトを Signal にルーティングします
ネイティブクライアント固有のルーティング:
- Telegram のデフォルトは承認者への DM(
target: "dm")です。発生元の Telegram チャットまたはトピックにも 承認プロンプトを表示するには、channelまたはbothに切り替えます。Telegram のフォーラムトピックでは、OpenClaw は 承認プロンプトと承認後のフォローアップでトピックを維持します。 - Discord と Telegram の承認者は、明示的に指定する(
execApprovals.approvers)か、commands.ownerAllowFromから推論できます。解決済みの承認者のみが承認または拒否できます。 - Slack の承認者は、明示的に指定する(
execApprovals.approvers)か、commands.ownerAllowFromから推論できます。Slack Plugin 承認の DM では、Slack の exec 承認者ではなく、allowFromとアカウントのデフォルトルーティングにある Slack Plugin 承認者を使用します。Slack のネイティブボタンは承認 ID の 種別を維持するため、plugin:ID では 2 つ目の Slack ローカルフォールバック層なしで Plugin 承認を解決できます。 - Google Chat のネイティブカードでは、メッセージテキスト内に手動の
/approveフォールバックを維持しますが、カードボタンの コールバックには不透明なアクショントークンのみが含まれます。承認 ID と判断は、サーバー側の保留状態から 復元されます。 - WhatsApp の絵文字承認は、対応するトップレベル転送ファミリーが WhatsApp にルーティングされている場合、 exec と Plugin の両方のプロンプトを処理します。ネイティブ発生元のプロンプトは直接バインドされます。共有宛先モードの 配信では、受理された WhatsApp メッセージの受信確認に、同じ型付き承認メタデータがバインドされます。
- Signal のリアクション承認は、対応するトップレベル転送ファミリーが有効で Signal にルーティングされている場合に限り、
exec と Plugin の両方のプロンプトを処理します。同一チャット内の直接的な Signal exec 承認では、
明示的な承認者なしでもローカルの
/approveフォールバックを抑制できます。Signal のリアクション解決には、channels.signal.allowFromまたはdefaultToに明示された Signal 承認者が引き続き必要です。 - Matrix のネイティブ DM/チャンネルルーティングとリアクションショートカットは、exec と Plugin の両方の承認を処理します。
Plugin の認可は引き続き
channels.matrix.dm.allowFromから取得します。Matrix のネイティブプロンプトには、 最初のプロンプトイベントにcom.openclaw.approvalカスタムイベントコンテンツが含まれるため、OpenClaw 対応の Matrix クライアントは構造化された承認状態を読み取ることができ、標準クライアントではプレーンテキストの/approveフォールバックが維持されます。 - Discord と Telegram のネイティブ承認ボタンは、トランスポート非公開のコールバックデータに明示的な exec または Plugin のオーナー種別を保持し、
そのオーナーのみを解決します。種別を持たない古い
/approveコントロールは、範囲を限定した互換性経路として残ります。 アクターが承認できるオーナー種別のみを試し、承認が見つからないという結果の後にのみ続行し、 承認 ID から所有権を推論することは決してありません。 - リクエスト元が承認者である必要はありません。
- オペレーター UI または設定済みの承認クライアントのいずれもリクエストを受理できない場合、プロンプトは
askFallbackにフォールバックします。
/diagnostics や /export-trajectory などの機密性の高いオーナー専用グループコマンドでは、承認プロンプトと最終結果に
非公開のオーナールーティングを使用します。OpenClaw はまず、オーナーがコマンドを実行したのと
同じ画面上の非公開経路を試します。その画面にオーナー用の非公開経路がない場合、
commands.ownerAllowFrom で利用可能な最初のオーナー経路にフォールバックします。そのため、Telegram が主要な
非公開インターフェースとして設定されている場合、Discord のグループコマンドでも承認と結果をオーナーの Telegram DM に
送信できます。グループチャットには短い確認応答のみが送られます。
参照:
公式モバイルオペレーターアプリ
公式の iOS および Android アプリでは、operator.admin 接続を使用している場合、またはペアリング済みの
operator.approvals デバイスがリクエストで明示的に指定された場合に、Gateway が所有する保留中の exec
承認も確認できます。アプリは
Control UI と同じサニタイズ済みの永続レコードを読み取り、種別を認識した判断を送信し、Gateway の正規の
先着回答結果を表示します。Apple Watch はペアリングされた iPhone を通じてこれらの承認プロンプトをミラーリングし、
1 回のみ許可するアクションと拒否アクションを提供します。Watch の Gateway 直接接続モードでは
承認を確認できません。
解決確認応答が失われても、送信した選択が確定するわけではありません。 アプリはコントロールを無効にして、レコードを再度読み取ります。別の画面が 先に回答していた場合、アプリは記録されたその判断を表示します。保留中のプロンプトは、それを発行した Gateway に引き続きバインドされるため、アクティブな Gateway を切り替えても古い承認 ID を リダイレクトできません。
macOS IPC フロー
OC_I18N_900004 セキュリティに関する注記:
- Unix ソケットモード
0600、トークンはexec-approvals.jsonに保存されます。 - 同一 UID のピアチェック。
- チャレンジ/レスポンス(nonce + HMAC トークン + リクエストハッシュ)+ 短い TTL。
FAQ
承認宛先で accountId と threadId を使用するのはどのような場合ですか?
チャンネルに複数の ID が設定されていて、承認プロンプトを特定の 1 つのアカウントから送信する必要がある場合は、
accountId を使用します。宛先がトピックまたはスレッドをサポートし、プロンプトをトップレベルのチャットではなく
そのスレッド内に留める必要がある場合は、threadId を使用します。
具体的な Telegram の例として、フォーラムトピックと 2 つの Telegram bot
アカウントを持つ運用スーパグループがあります。to 値はスーパグループを指定し、accountId は bot アカウントを選択し、
threadId はフォーラムトピックを選択します:
OC_I18N_900005
この設定では、転送された exec 承認は ops-bot Telegram アカウントから、チャット
-1001234567890 のトピック 77 に投稿されます。accountId のない宛先ではチャンネルのデフォルトアカウントを使用し、
threadId のない宛先ではトップレベルの宛先に投稿されます。
承認がセッションに送信された場合、そのセッション内の誰でも承認できますか?
いいえ。セッション配信は、プロンプトが表示される場所のみを制御します。それ自体で、そのチャットの すべての参加者に承認権限を付与するわけではありません。
一般的な同一チャットの /approve では、送信者がそのチャンネルセッション内でコマンドを実行する権限を
すでに持っている必要があります。チャンネルで明示的な承認者が公開されている場合、その承認者は
そのセッションで通常のコマンド実行権限を持っていなくても、/approve アクションを認可できます。
一部のチャンネルでは、より厳格です。Discord、Telegram、Matrix、Slack のネイティブ承認 DM、および同様の
ネイティブ承認クライアントでは、解決済みの承認者リストを承認の認可に使用します。たとえば、
Telegram のフォーラムトピックにある承認プロンプトはトピック内の全員に表示される場合がありますが、
channels.telegram.execApprovals.approvers または
commands.ownerAllowFrom から解決された数値の Telegram ユーザー ID のみが承認または拒否できます。