
























@@ -4,35 +4,44 @@ read_when:
44 - Configuring exec approvals or allowlists
55 - Implementing exec approval UX in the macOS app
66 - Reviewing sandbox escape prompts and implications
7-title: "Exec Approvals"
7+title: "Exec approvals"
88---
991010# Exec approvals
111112-Exec approvals are the **companion app / node host guardrail** for letting a sandboxed agent run
13-commands on a real host (`gateway` or `node`). Think of it like a safety interlock:
14-commands are allowed only when policy + allowlist + (optional) user approval all agree.
15-Exec approvals are **in addition** to tool policy and elevated gating (unless elevated is set to `full`, which skips approvals).
16-Effective policy is the **stricter** of `tools.exec.*` and approvals defaults; if an approvals field is omitted, the `tools.exec` value is used.
17-Host exec also uses the local approvals state on that machine. A host-local
18-`ask: "always"` in `~/.openclaw/exec-approvals.json` keeps prompting even if
19-session or config defaults request `ask: "on-miss"`.
20-Use `openclaw approvals get`, `openclaw approvals get --gateway`, or
21-`openclaw approvals get --node <id|name|ip>` to inspect the requested policy,
22-host policy sources, and the effective result.
23-For the local machine, `openclaw exec-policy show` exposes the same merged view and
24-`openclaw exec-policy set|preset` can synchronize the local requested policy with the
25-local host approvals file in one step. When a local scope requests `host=node`,
26-`openclaw exec-policy show` reports that scope as node-managed at runtime instead of
27-pretending the local approvals file is the effective source of truth.
28-29-If the companion app UI is **not available**, any request that requires a prompt is
30-resolved by the **ask fallback** (default: deny).
31-32-Native chat approval clients can also expose channel-specific affordances on the
33-pending approval message. For example, Matrix can seed reaction shortcuts on the
34-approval prompt (`✅` allow once, `❌` deny, and `♾️` allow always when available)
35-while still leaving the `/approve ...` commands in the message as a fallback.
12+Exec approvals are the **companion app / node host guardrail** for letting a
13+sandboxed agent run commands on a real host (`gateway` or `node`). A safety
14+interlock: commands are allowed only when policy + allowlist + (optional) user
15+approval all agree. Exec approvals stack **on top of** tool policy and elevated
16+gating (unless elevated is set to `full`, which skips approvals).
17+18+<Note>
19+Effective policy is the **stricter** of `tools.exec.*` and approvals defaults;
20+if an approvals field is omitted, the `tools.exec` value is used. Host exec
21+also uses local approvals state on that machine — a host-local `ask: "always"`
22+in `~/.openclaw/exec-approvals.json` keeps prompting even if session or config
23+defaults request `ask: "on-miss"`.
24+</Note>
25+26+## Inspecting the effective policy
27+28+- `openclaw approvals get`, `... --gateway`, `... --node <id|name|ip>` — show requested policy, host policy sources, and the effective result.
29+- `openclaw exec-policy show` — local-machine merged view.
30+- `openclaw exec-policy set|preset` — synchronize the local requested policy with the local host approvals file in one step.
31+32+When a local scope requests `host=node`, `exec-policy show` reports that scope
33+as node-managed at runtime instead of pretending the local approvals file is
34+the source of truth.
35+36+If the companion app UI is **not available**, any request that would normally
37+prompt is resolved by the **ask fallback** (default: deny).
38+39+<Tip>
40+Native chat approval clients can seed channel-specific affordances on the
41+pending approval message. For example, Matrix seeds reaction shortcuts (`✅`
42+allow once, `❌` deny, `♾️` allow always) while still leaving `/approve ...`
43+commands in the message as a fallback.
44+</Tip>
36453746## Where it applies
3847@@ -268,60 +277,19 @@ Important trust notes:
268277269278## Safe bins (stdin-only)
270279271-`tools.exec.safeBins` defines a small list of **stdin-only** binaries (for example `cut`)
272-that can run in allowlist mode **without** explicit allowlist entries. Safe bins reject
273-positional file args and path-like tokens, so they can only operate on the incoming stream.
274-Treat this as a narrow fast-path for stream filters, not a general trust list.
275-Do **not** add interpreter or runtime binaries (for example `python3`, `node`, `ruby`, `bash`, `sh`, `zsh`) to `safeBins`.
276-If a command can evaluate code, execute subcommands, or read files by design, prefer explicit allowlist entries and keep approval prompts enabled.
277-Custom safe bins must define an explicit profile in `tools.exec.safeBinProfiles.<bin>`.
278-Validation is deterministic from argv shape only (no host filesystem existence checks), which
279-prevents file-existence oracle behavior from allow/deny differences.
280-File-oriented options are denied for default safe bins (for example `sort -o`, `sort --output`,
281-`sort --files0-from`, `sort --compress-program`, `sort --random-source`,
282-`sort --temporary-directory`/`-T`, `wc --files0-from`, `jq -f/--from-file`,
283-`grep -f/--file`).
284-Safe bins also enforce explicit per-binary flag policy for options that break stdin-only
285-behavior (for example `sort -o/--output/--compress-program` and grep recursive flags).
286-Long options are validated fail-closed in safe-bin mode: unknown flags and ambiguous
287-abbreviations are rejected.
288-Denied flags by safe-bin profile:
289-290-[//]: # "SAFE_BIN_DENIED_FLAGS:START"
291-292-- `grep`: `--dereference-recursive`, `--directories`, `--exclude-from`, `--file`, `--recursive`, `-R`, `-d`, `-f`, `-r`
293-- `jq`: `--argfile`, `--from-file`, `--library-path`, `--rawfile`, `--slurpfile`, `-L`, `-f`
294-- `sort`: `--compress-program`, `--files0-from`, `--output`, `--random-source`, `--temporary-directory`, `-T`, `-o`
295-- `wc`: `--files0-from`
296-297-[//]: # "SAFE_BIN_DENIED_FLAGS:END"
298-299-Safe bins also force argv tokens to be treated as **literal text** at execution time (no globbing
300-and no `$VARS` expansion) for stdin-only segments, so patterns like `*` or `$HOME/...` cannot be
301-used to smuggle file reads.
302-Safe bins must also resolve from trusted binary directories (system defaults plus optional
303-`tools.exec.safeBinTrustedDirs`). `PATH` entries are never auto-trusted.
304-Default trusted safe-bin directories are intentionally minimal: `/bin`, `/usr/bin`.
305-If your safe-bin executable lives in package-manager/user paths (for example
306-`/opt/homebrew/bin`, `/usr/local/bin`, `/opt/local/bin`, `/snap/bin`), add them explicitly
307-to `tools.exec.safeBinTrustedDirs`.
308-Shell chaining and redirections are not auto-allowed in allowlist mode.
309-310-Shell chaining (`&&`, `||`, `;`) is allowed when every top-level segment satisfies the allowlist
311-(including safe bins or skill auto-allow). Redirections remain unsupported in allowlist mode.
312-Command substitution (`$()` / backticks) is rejected during allowlist parsing, including inside
313-double quotes; use single quotes if you need literal `$()` text.
314-On macOS companion-app approvals, raw shell text containing shell control or expansion syntax
315-(`&&`, `||`, `;`, `|`, `` ` ``, `$`, `<`, `>`, `(`, `)`) is treated as an allowlist miss unless
316-the shell binary itself is allowlisted.
317-For shell wrappers (`bash|sh|zsh ... -c/-lc`), request-scoped env overrides are reduced to a
318-small explicit allowlist (`TERM`, `LANG`, `LC_*`, `COLORTERM`, `NO_COLOR`, `FORCE_COLOR`).
319-For allow-always decisions in allowlist mode, known dispatch wrappers
320-(`env`, `nice`, `nohup`, `stdbuf`, `timeout`) persist inner executable paths instead of wrapper
321-paths. Shell multiplexers (`busybox`, `toybox`) are also unwrapped for shell applets (`sh`, `ash`,
322-etc.) so inner executables are persisted instead of multiplexer binaries. If a wrapper or
323-multiplexer cannot be safely unwrapped, no allowlist entry is persisted automatically.
324-If you allowlist interpreters like `python3` or `node`, prefer `tools.exec.strictInlineEval=true` so inline eval still requires an explicit approval. In strict mode, `allow-always` can still persist benign interpreter/script invocations, but inline-eval carriers are not persisted automatically.
280+`tools.exec.safeBins` defines a small list of **stdin-only** binaries (for
281+example `cut`) that can run in allowlist mode **without** explicit allowlist
282+entries. Safe bins reject positional file args and path-like tokens, so they
283+can only operate on the incoming stream. Treat this as a narrow fast-path for
284+stream filters, not a general trust list.
285+286+<Warning>
287+Do **not** add interpreter or runtime binaries (for example `python3`, `node`,
288+`ruby`, `bash`, `sh`, `zsh`) to `safeBins`. If a command can evaluate code,
289+execute subcommands, or read files by design, prefer explicit allowlist entries
290+and keep approval prompts enabled. Custom safe bins must define an explicit
291+profile in `tools.exec.safeBinProfiles.<bin>`.
292+</Warning>
325293326294Default safe bins:
327295@@ -331,10 +299,78 @@ Default safe bins:
331299332300[//]: # "SAFE_BIN_DEFAULTS:END"
333301334-`grep` and `sort` are not in the default list. If you opt in, keep explicit allowlist entries for
335-their non-stdin workflows.
336-For `grep` in safe-bin mode, provide the pattern with `-e`/`--regexp`; positional pattern form is
337-rejected so file operands cannot be smuggled as ambiguous positionals.
302+`grep` and `sort` are not in the default list. If you opt in, keep explicit
303+allowlist entries for their non-stdin workflows. For `grep` in safe-bin mode,
304+provide the pattern with `-e`/`--regexp`; positional pattern form is rejected
305+so file operands cannot be smuggled as ambiguous positionals.
306+307+<AccordionGroup>
308+ <Accordion title="Argv validation and denied flags">
309+Validation is deterministic from argv shape only (no host filesystem
310+existence checks), which prevents file-existence oracle behavior from
311+allow/deny differences. File-oriented options are denied for default safe
312+bins; long options are validated fail-closed (unknown flags and ambiguous
313+abbreviations are rejected).
314+315+Denied flags by safe-bin profile:
316+317+[//]: # "SAFE_BIN_DENIED_FLAGS:START"
318+319+- `grep`: `--dereference-recursive`, `--directories`, `--exclude-from`, `--file`, `--recursive`, `-R`, `-d`, `-f`, `-r`
320+- `jq`: `--argfile`, `--from-file`, `--library-path`, `--rawfile`, `--slurpfile`, `-L`, `-f`
321+- `sort`: `--compress-program`, `--files0-from`, `--output`, `--random-source`, `--temporary-directory`, `-T`, `-o`
322+- `wc`: `--files0-from`
323+324+[//]: # "SAFE_BIN_DENIED_FLAGS:END"
325+326+Safe bins also force argv tokens to be treated as **literal text** at
327+execution time (no globbing and no `$VARS` expansion) for stdin-only
328+segments, so patterns like `*` or `$HOME/...` cannot be used to smuggle
329+file reads.
330+331+ </Accordion>
332+333+ <Accordion title="Trusted binary directories">
334+Safe bins must resolve from trusted binary directories (system defaults
335+plus optional `tools.exec.safeBinTrustedDirs`). `PATH` entries are never
336+auto-trusted. Default trusted directories are intentionally minimal:
337+`/bin`, `/usr/bin`. If your safe-bin executable lives in
338+package-manager/user paths (for example `/opt/homebrew/bin`,
339+`/usr/local/bin`, `/opt/local/bin`, `/snap/bin`), add them explicitly to
340+`tools.exec.safeBinTrustedDirs`.
341+ </Accordion>
342+343+ <Accordion title="Shell chaining, wrappers, and multiplexers">
344+Shell chaining (`&&`, `||`, `;`) is allowed when every top-level segment
345+satisfies the allowlist (including safe bins or skill auto-allow).
346+Redirections remain unsupported in allowlist mode. Command substitution
347+(`$()` / backticks) is rejected during allowlist parsing, including inside
348+double quotes; use single quotes if you need literal `$()` text.
349+350+On macOS companion-app approvals, raw shell text containing shell control
351+or expansion syntax (`&&`, `||`, `;`, `|`, `` ` ``, `$`, `<`, `>`, `(`,
352+`)`) is treated as an allowlist miss unless the shell binary itself is
353+allowlisted.
354+355+For shell wrappers (`bash|sh|zsh ... -c/-lc`), request-scoped env
356+overrides are reduced to a small explicit allowlist (`TERM`, `LANG`,
357+`LC_*`, `COLORTERM`, `NO_COLOR`, `FORCE_COLOR`).
358+359+For `allow-always` decisions in allowlist mode, known dispatch wrappers
360+(`env`, `nice`, `nohup`, `stdbuf`, `timeout`) persist the inner executable
361+path instead of the wrapper path. Shell multiplexers (`busybox`, `toybox`)
362+are unwrapped for shell applets (`sh`, `ash`, etc.) the same way. If a
363+wrapper or multiplexer cannot be safely unwrapped, no allowlist entry is
364+persisted automatically.
365+366+If you allowlist interpreters like `python3` or `node`, prefer
367+`tools.exec.strictInlineEval=true` so inline eval still requires an
368+explicit approval. In strict mode, `allow-always` can still persist benign
369+interpreter/script invocations, but inline-eval carriers are not persisted
370+automatically.
371+372+ </Accordion>
373+</AccordionGroup>
338374339375### Safe bins versus allowlist
340376@@ -642,20 +678,29 @@ stale results from a prior successful run.
642678643679- **full** is powerful; prefer allowlists when possible.
644680- **ask** keeps you in the loop while still allowing fast approvals.
645-- Per-agent allowlists prevent one agent’s approvals from leaking into others.
681+- Per-agent allowlists prevent one agent's approvals from leaking into others.
646682- Approvals only apply to host exec requests from **authorized senders**. Unauthorized senders cannot issue `/exec`.
647-- `/exec security=full` is a session-level convenience for authorized operators and skips approvals by design.
648- To hard-block host exec, set approvals security to `deny` or deny the `exec` tool via tool policy.
649-650-Related:
651-652-- [Exec tool](/tools/exec)
653-- [Elevated mode](/tools/elevated)
654-- [Skills](/tools/skills)
683+- `/exec security=full` is a session-level convenience for authorized operators and skips approvals by design. To hard-block host exec, set approvals security to `deny` or deny the `exec` tool via tool policy.
655684656685## Related
657686658-- [Exec](/tools/exec) — shell command execution tool
659-- [Sandboxing](/gateway/sandboxing) — sandbox modes and workspace access
660-- [Security](/gateway/security) — security model and hardening
661-- [Sandbox vs Tool Policy vs Elevated](/gateway/sandbox-vs-tool-policy-vs-elevated) — when to use each
687+<CardGroup cols={2}>
688+ <Card title="Exec tool" href="/tools/exec" icon="terminal">
689+Shell command execution tool.
690+ </Card>
691+ <Card title="Elevated mode" href="/tools/elevated" icon="shield-exclamation">
692+Break-glass path that also skips approvals.
693+ </Card>
694+ <Card title="Sandboxing" href="/gateway/sandboxing" icon="box">
695+Sandbox modes and workspace access.
696+ </Card>
697+ <Card title="Security" href="/gateway/security" icon="lock">
698+Security model and hardening.
699+ </Card>
700+ <Card title="Sandbox vs tool policy vs elevated" href="/gateway/sandbox-vs-tool-policy-vs-elevated" icon="sliders">
701+When to reach for each control.
702+ </Card>
703+ <Card title="Skills" href="/tools/skills" icon="sparkles">
704+Skill-backed auto-allow behavior.
705+ </Card>
706+</CardGroup>
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。