2026-01-18 01:33:52 +00:00
|
|
|
|
---
|
2026-01-18 04:27:33 +00:00
|
|
|
|
summary: "Exec approvals, allowlists, and sandbox escape prompts"
|
2026-01-18 01:33:52 +00:00
|
|
|
|
read_when:
|
|
|
|
|
|
- Configuring exec approvals or allowlists
|
|
|
|
|
|
- Implementing exec approval UX in the macOS app
|
|
|
|
|
|
- Reviewing sandbox escape prompts and implications
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-01-18 04:27:33 +00:00
|
|
|
|
# Exec approvals
|
|
|
|
|
|
|
|
|
|
|
|
Exec approvals are the **companion app guardrail** for letting a sandboxed agent run
|
|
|
|
|
|
commands on a real host (`gateway` or `node`). Think of it like a safety interlock:
|
|
|
|
|
|
commands are allowed only when policy + allowlist + (optional) user approval all agree.
|
|
|
|
|
|
Exec approvals are **in addition** to tool policy and elevated gating.
|
|
|
|
|
|
|
|
|
|
|
|
If the companion app UI is **not available**, any request that requires a prompt is
|
|
|
|
|
|
resolved by the **ask fallback** (default: deny).
|
|
|
|
|
|
|
|
|
|
|
|
## Where it applies
|
|
|
|
|
|
|
|
|
|
|
|
Exec approvals are enforced locally on the execution host:
|
|
|
|
|
|
- **gateway host** → `clawdbot` process on the gateway machine
|
|
|
|
|
|
- **node host** → node runner (macOS companion app or headless node)
|
|
|
|
|
|
|
|
|
|
|
|
## Settings and storage
|
|
|
|
|
|
|
|
|
|
|
|
Approvals live in a local JSON file:
|
|
|
|
|
|
|
|
|
|
|
|
`~/.clawdbot/exec-approvals.json`
|
|
|
|
|
|
|
|
|
|
|
|
Example schema:
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"version": 1,
|
|
|
|
|
|
"socket": {
|
|
|
|
|
|
"path": "~/.clawdbot/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": [
|
|
|
|
|
|
{
|
|
|
|
|
|
"pattern": "~/Projects/**/bin/rg",
|
|
|
|
|
|
"lastUsedAt": 1737150000000,
|
|
|
|
|
|
"lastUsedCommand": "rg -n TODO",
|
|
|
|
|
|
"lastResolvedPath": "/Users/user/Projects/.../bin/rg"
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## Policy knobs
|
|
|
|
|
|
|
|
|
|
|
|
### Security (`exec.security`)
|
|
|
|
|
|
- **deny**: block all host exec requests.
|
|
|
|
|
|
- **allowlist**: allow only allowlisted commands.
|
|
|
|
|
|
- **full**: allow everything (equivalent to elevated).
|
|
|
|
|
|
|
|
|
|
|
|
### Ask (`exec.ask`)
|
|
|
|
|
|
- **off**: never prompt.
|
|
|
|
|
|
- **on-miss**: prompt only when allowlist does not match.
|
|
|
|
|
|
- **always**: prompt on every command.
|
|
|
|
|
|
|
|
|
|
|
|
### Ask fallback (`askFallback`)
|
|
|
|
|
|
If a prompt is required but no UI is reachable, fallback decides:
|
|
|
|
|
|
- **deny**: block.
|
|
|
|
|
|
- **allowlist**: allow only if allowlist matches.
|
|
|
|
|
|
- **full**: allow.
|
2026-01-18 01:33:52 +00:00
|
|
|
|
|
|
|
|
|
|
## Allowlist (per agent)
|
|
|
|
|
|
|
2026-01-18 04:27:33 +00:00
|
|
|
|
Allowlists are **per agent**. If multiple agents exist, switch which agent you’re
|
|
|
|
|
|
editing in the macOS app. Patterns are **case-insensitive glob matches**.
|
2026-01-18 01:33:52 +00:00
|
|
|
|
|
|
|
|
|
|
Examples:
|
|
|
|
|
|
- `~/Projects/**/bin/bird`
|
|
|
|
|
|
- `~/.local/bin/*`
|
|
|
|
|
|
- `/opt/homebrew/bin/rg`
|
|
|
|
|
|
|
|
|
|
|
|
Each allowlist entry tracks:
|
2026-01-18 04:27:33 +00:00
|
|
|
|
- **last used** timestamp
|
2026-01-18 01:33:52 +00:00
|
|
|
|
- **last used command**
|
2026-01-18 04:27:33 +00:00
|
|
|
|
- **last resolved path**
|
2026-01-18 01:33:52 +00:00
|
|
|
|
|
2026-01-18 04:27:33 +00:00
|
|
|
|
## Auto-allow skill CLIs
|
2026-01-18 01:33:52 +00:00
|
|
|
|
|
2026-01-18 04:27:33 +00:00
|
|
|
|
When **Auto-allow skill CLIs** is enabled, executables referenced by known skills
|
|
|
|
|
|
are treated as allowlisted (node hosts only). Disable this if you want strict
|
|
|
|
|
|
manual allowlists.
|
2026-01-18 01:33:52 +00:00
|
|
|
|
|
|
|
|
|
|
## Approval flow
|
|
|
|
|
|
|
2026-01-18 04:27:33 +00:00
|
|
|
|
When a prompt is required, the companion app displays a confirmation dialog with:
|
2026-01-18 01:33:52 +00:00
|
|
|
|
- command + args
|
|
|
|
|
|
- cwd
|
2026-01-18 04:27:33 +00:00
|
|
|
|
- agent id
|
|
|
|
|
|
- resolved executable path
|
|
|
|
|
|
- host + policy metadata
|
2026-01-18 01:33:52 +00:00
|
|
|
|
|
|
|
|
|
|
Actions:
|
|
|
|
|
|
- **Allow once** → run now
|
2026-01-18 04:27:33 +00:00
|
|
|
|
- **Always allow** → add to allowlist + run
|
2026-01-18 01:33:52 +00:00
|
|
|
|
- **Deny** → block
|
|
|
|
|
|
|
|
|
|
|
|
## System events
|
|
|
|
|
|
|
2026-01-18 04:27:33 +00:00
|
|
|
|
Exec lifecycle is surfaced as system messages:
|
|
|
|
|
|
- `exec.started`
|
|
|
|
|
|
- `exec.finished`
|
|
|
|
|
|
- `exec.denied`
|
2026-01-18 01:33:52 +00:00
|
|
|
|
|
2026-01-18 04:27:33 +00:00
|
|
|
|
These are posted to the agent’s session after the node reports the event.
|
2026-01-18 01:33:52 +00:00
|
|
|
|
|
|
|
|
|
|
## Implications
|
|
|
|
|
|
|
2026-01-18 04:27:33 +00:00
|
|
|
|
- **full** is powerful; prefer allowlists when possible.
|
|
|
|
|
|
- **ask** keeps you in the loop while still allowing fast approvals.
|
|
|
|
|
|
- Per-agent allowlists prevent one agent’s approvals from leaking into others.
|
2026-01-18 01:33:52 +00:00
|
|
|
|
|
|
|
|
|
|
Related:
|
|
|
|
|
|
- [Exec tool](/tools/exec)
|
|
|
|
|
|
- [Elevated mode](/tools/elevated)
|
|
|
|
|
|
- [Skills](/tools/skills)
|