Managing Exec Approvals for Safe Command Execution
We have all been there: you are building an automated agent and you want it to actually do things, but giving a sandboxed process free reign over your terminal feels risky. You want the productivity of automation without the constant worry that a script might execute something unexpected on your machine.
I find that the best way to handle this is with a proper safety interlock. Exec approvals act as a guardrail for your host, ensuring that commands only run when your policy, allowlist, and manual approval are all in sync.
What You’ll Need
Section titled “What You’ll Need”- An execution host (either a
gatewayor anode). - The
openclawprocess or the macOS companion app.
Quick Start
Section titled “Quick Start”Exec approvals are enforced locally on your execution host. If you are on a gateway, the openclaw process handles it. If you are on macOS, the node host service sends the request to your macOS app to show the UI.
To get started, you need to configure the local JSON file where these settings live.
- Locate your config file: Open
~/.openclaw/exec-approvals.jsonon your host. - Define your policy: Use the schema below to set your defaults and agent-specific rules.
{ "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" } ] } }}I recommend setting security to allowlist for specific agents. This ensures that only known patterns can run without you manually clicking “approve” every single time.
Troubleshooting
Section titled “Troubleshooting”The companion app UI is not appearing
Section titled “The companion app UI is not appearing”If the macOS companion app UI is unavailable, any command that requires a prompt will fail. The system uses the askFallback setting (which defaults to deny) to resolve the request safely.
Command denied despite previous approval
Section titled “Command denied despite previous approval”The system binds the execution context, including the file path and script content. If a script changes after you approve it but before it executes, the run is denied to prevent “drifted content” from running on your machine.
If you have more questions about setting this up, check out the AI Setup Assistant.
What’s Next
Section titled “What’s Next”I’ve spent a lot of time worrying about what happens when an automated agent tries to run commands on my local machine. It is a stressful balance: you want the agent to be helpful, but you don’t want to give it total control over your terminal. I often find myself hovering over the keyboard, wondering if I should let a process execute or block it entirely to stay safe.
Setting up the right boundaries makes a huge difference in how much you can trust your tools. I’ll show you how to use policy knobs to get that control back.
What You’ll Need
Section titled “What You’ll Need”- A running agent instance (macOS app or headless node).
- Access to your agent configuration settings.
- Binary paths for the tools you want to allowlist.
- Gateway RPC connection (if using skill CLIs).
Quick Start
Section titled “Quick Start”You can get your security policy running in about five minutes by following these steps:
- Set your security level: Choose between
deny,allowlist, orfullin yourexec.securitysettings. - Define prompt behavior: Set
exec.askto decide when you want to be notified. - Map your binaries: Add specific binary paths to your allowlist using glob patterns.
- Handle fallbacks: Configure
askFallbackfor situations where the UI isn’t available to show a prompt.
Security Knobs
Section titled “Security Knobs”I recommend looking at these three main categories to define how your agent behaves.
Security (exec.security)
Section titled “Security (exec.security)”This is your primary toggle for host execution:
- deny: This blocks all host exec requests immediately.
- allowlist: Only commands you have specifically approved will run.
- full: This allows everything, which is the same as elevated access.
Ask (exec.ask)
Section titled “Ask (exec.ask)”This controls the frequency of prompts:
- off: You will never see a prompt.
- on-miss: You only get a prompt if the command isn’t in your allowlist.
- always: You get a prompt for every single command.
Ask fallback (askFallback)
Section titled “Ask fallback (askFallback)”If the system needs to prompt you but can’t reach a UI, it looks at this setting:
- deny: It blocks the command.
- allowlist: It only allows the command if it matches your allowlist.
- full: It allows the execution.
Managing the Allowlist
Section titled “Managing the Allowlist”Allowlists are specific to each agent. If you have several agents, I suggest switching between them in the macOS app to edit their individual lists.
The patterns use case-insensitive glob matches. A very important detail: these must resolve to binary paths. If you only enter a basename (like just rg), it will be ignored. If you are moving from older versions, agents.default entries are migrated to agents.main when you load them.
Here are the path formats you should use:
~/Projects/**/bin/peekaboo~/.local/bin/*/opt/homebrew/bin/rg
Each entry in your list tracks the stable UUID (id), the last used timestamp, the last used command, and the last resolved path.
Auto-allow Skill CLIs
Section titled “Auto-allow Skill CLIs”If you enable Auto-allow skill CLIs, the system treats executables from known skills as if they were already allowlisted. This happens on your macOS node or headless node host. It uses skills.bins over the Gateway RPC to get the list.
I suggest disabling this if you prefer a strict manual setup. It is a convenience feature for environments where the Gateway and the node share the same trust boundary. If you need explicit trust, set autoAllowSkills: false and stick to manual path entries.
Troubleshooting
Section titled “Troubleshooting”The allowlist is ignoring my entries Check if you are using basename-only entries. The system requires full paths or glob patterns that resolve to binary paths. Basenames are ignored.
Commands are failing when I’m away from my computer
This usually happens when a prompt is required but the UI is unreachable. Check your askFallback setting. If it is set to deny, the command will fail whenever the prompt cannot be displayed.
If you need help configuring these knobs for your specific setup, check out the AI Setup Assistant.
What’s Next
Section titled “What’s Next”- Configuring Gateway RPC
- Managing Agent Identities
- Advanced Glob Pattern Matching
- Headless Node Setup
I’ve been there: you’re in the middle of a task, and you just want to pipe some output through jq or head to see what’s going on. But instead of getting your data, you’re hit with a security prompt asking for permission to run a basic command. It breaks your flow and makes simple text processing feel like a chore.
I want to show you how to use Safe Bins. These are stdin-only binaries that can run in allowlist mode without needing explicit entries for every single variation. Think of it as a fast-path for stream filters.
What You’ll Need
Section titled “What You’ll Need”- Access to your
tools.execconfiguration files. - The
openclawCLI tool for security audits. - Binaries located in trusted system paths like
/binor/usr/bin.
Quick Start
Section titled “Quick Start”You can get started with safe bins by identifying which tools you use most for stream processing. By default, the system trusts a specific set of tools when they are used strictly as filters.
- Check the defaults: The following tools are already configured as safe bins:
jq,cut,uniq,head,tail,tr, andwc. - Verify the path: Ensure your binaries live in
/binor/usr/bin. If you use Homebrew or other managers, you’ll need to add those paths totools.exec.safeBinTrustedDirs. - Run a command: Try piping data into a safe bin. For example:
cat data.json | jq .. It should run without a manual approval prompt.
How Safe Bins Work
Section titled “How Safe Bins Work”Safe bins are restricted to stdin-only operations. They reject positional file arguments and path-like tokens. This means they can only work on the data coming through the pipe, not files on your disk.
I recommend treating this as a narrow trust list for text transforms. Do not add interpreters or runtimes like python3, node, ruby, or bash to your safeBins. If a tool can execute code or read files by design, stick to the explicit allowlist.
Flag Validation and Restrictions
Section titled “Flag Validation and Restrictions”Validation is deterministic based on the shape of the command arguments. The system doesn’t check the host filesystem; it just looks at the flags you are trying to use. If a flag allows a tool to read a file or write output, it is denied.
Here are the flags that will cause a safe bin command to be rejected:
- grep:
--dereference-recursive,--directories,--exclude-from,--file,--recursive,-R,-d,-f,-r - jq:
--argfile,--from-file,--library-path,--rawfile,--slurpfile,-L,-f - sort:
--compress-program,--files0-from,--output,--random-source,--temporary-directory,-T,-o - wc:
--files0-from
Safe bins also force tokens to be treated as literal text. This means no globbing with * and no $VARS expansion. This prevents anyone from smuggling file reads into a simple filter command.
Shell Chaining and Redirections
Section titled “Shell Chaining and Redirections”Shell chaining using &&, ||, or ; is allowed as long as every individual segment satisfies the allowlist requirements. However, redirections (like > or <) are not supported in allowlist mode.
If you use command substitution like $() or backticks, the allowlist parser will reject it. If you actually need the literal text $(), use single quotes.
Custom Safe Bin Profiles
Section titled “Custom Safe Bin Profiles”If you have a custom tool that acts as a filter, you can define a profile for it. Here is how you would configure a custom filter in your JSON config:
{ tools: { exec: { safeBins: ["jq", "myfilter"], safeBinProfiles: { myfilter: { minPositional: 0, maxPositional: 0, allowedValueFlags: ["-n", "--limit"], deniedFlags: ["-f", "--file", "-c", "--command"], }, }, }, },}Safe Bins vs. Allowlist
Section titled “Safe Bins vs. Allowlist”It helps to know when to use a safe bin versus a standard allowlist entry.
| Topic | tools.exec.safeBins | Allowlist (exec-approvals.json) |
|---|---|---|
| Goal | Auto-allow narrow stdin filters | Explicitly trust specific executables |
| Match type | Executable name + safe-bin argv policy | Resolved executable path glob pattern |
| Argument scope | Restricted by profile and literal rules | Path match only; args are your responsibility |
| Typical examples | jq, head, tail, wc | python3, node, ffmpeg, custom CLIs |
| Best use | Low-risk text transforms in pipelines | Any tool with broader behavior or side effects |
Troubleshooting
Section titled “Troubleshooting”If things aren’t working as expected, check these common scenarios:
- Interpreter Warnings: If you put an interpreter in
safeBinswithout a profile,openclaw security auditwill warn you withtools.exec.safe_bins_interpreter_unprofiled. - Missing Profiles: If you added a custom bin but forgot the profile, run
openclaw doctor --fix. It can scaffold the missingsafeBinProfiles.<bin>entries as{}for you to fill in later. - Grep or Sort issues: Remember that
grepandsortare not in the default list. If you opt-in, use-eor--regexpforgreppatterns, as positional patterns are rejected to prevent file smuggling. - Path issues: If your binary is in
/usr/local/binor/opt/homebrew/bin, it won’t be trusted by default. Add these totools.exec.safeBinTrustedDirs.
If you need help getting your configuration just right, check out the AI Setup Assistant.
What’s Next
Section titled “What’s Next”I’ve often felt that slight hesitation before letting an automated tool run commands on my machine. You want the speed of automation, but you also want to know exactly what is happening in your terminal. It is a common balance between moving fast and staying safe.
Setting up execution approvals helps you find that balance. Instead of giving an agent a blank check, you can decide exactly which commands are safe and which ones need a manual thumbs-up.
What You’ll Need
Section titled “What You’ll Need”- Access to the Control UI.
- Nodes that advertise
system.execApprovals.get/set(this includes the macOS app or headless node hosts). - The
openclawCLI if you prefer terminal-based management.
Quick Start
Section titled “Quick Start”You can manage everything through the Control UI → Nodes → Exec approvals card. Here is how I usually set it up:
- Pick a scope: Choose between Defaults or a specific agent.
- Tweak the policy: Adjust your settings and add or remove allowlist patterns.
- Check metadata: The UI shows last used metadata for each pattern, which helps you identify and remove patterns you no longer use.
- Save: Apply your changes.
If you are working with a node that doesn’t show up in the UI yet, you can use the CLI:
openclaw approvalsThis command supports editing for both the gateway and specific nodes.
The Approval Flow
Section titled “The Approval Flow”When an agent needs to run a command, the gateway sends an exec.approval.requested signal. You will see a confirmation dialog that includes:
- The command and its arguments.
- The
cwd(current working directory). - The agent ID and the resolved executable path.
- Host and policy metadata.
You have three choices when the dialog pops up:
- Allow once: Runs the command this one time.
- Always allow: Runs the command and adds it to your allowlist.
- Deny: Blocks the execution.
Troubleshooting
Section titled “Troubleshooting”Node does not advertise approvals
Section titled “Node does not advertise approvals”If a node does not advertise system.execApprovals.get/set yet, you won’t be able to edit it through the UI. In this case, I recommend editing the local configuration file directly at:
~/.openclaw/exec-approvals.json
Approval Timeouts
Section titled “Approval Timeouts”When approvals are required, the tool returns an approval ID immediately. If you don’t make a decision before the timeout, the system treats it as an approval timeout. This will be surfaced in your logs as a denial reason. You can correlate these events by looking for the Exec finished or Exec denied system events using that specific ID.
If you need more help getting this configured, check out the AI Setup Assistant.
What’s Next
Section titled “What’s Next”I hate being tethered to a specific terminal window just to wait for an execution approval. It is a common frustration: you start a task, it hits a security gate, and then you have to hunt down the right tab to click “Allow.” I prefer getting those notifications where I already spend my time—in chat.
If you are tired of context-switching to manage permissions, you can route these prompts directly to your team’s communication tools. It keeps the workflow moving without sacrificing security.
What You’ll Need
Section titled “What You’ll Need”- Authorized senders for host exec requests.
- A configured chat channel (Slack, Telegram, Discord, or a plugin channel).
- Access to your configuration file.
Quick Start
Section titled “Quick Start”You can forward exec approval prompts to any chat channel and handle them with the /approve command. This setup uses the normal outbound delivery pipeline to keep things consistent.
1. Configure the Forwarding
Section titled “1. Configure the Forwarding”Add the following block to your configuration. You can filter by agent or session and define specific targets like Slack or Telegram.
{ approvals: { exec: { enabled: true, mode: "session", // "session" | "targets" | "both" agentFilter: ["main"], sessionFilter: ["discord"], // substring or regex targets: [ { channel: "slack", to: "U12345678" }, { channel: "telegram", to: "123456789" }, ], }, },}2. Approve via Chat
Section titled “2. Approve via Chat”When a prompt appears in your channel, you can respond with one of these three commands:
/approve <id> allow-once/approve <id> allow-always/approve <id> denyHow it Works on macOS
Section titled “How it Works on macOS”For those on macOS, the system follows a specific IPC (Inter-Process Communication) flow to ensure the UI and the background services stay in sync:
Gateway -> Node Service (WS) | IPC (UDS + token + HMAC + TTL) v Mac App (UI + approvals + system.run)I want to highlight the security measures here. The Unix socket uses mode 0600, and the token is stored in exec-approvals.json. The system performs a same-UID peer check and uses a challenge/response mechanism with a short TTL to keep things tight.
System Events
Section titled “System Events”The exec lifecycle is surfaced as system messages. These are posted to the agent’s session after the node reports the event:
Exec running: This appears if the command exceeds the running notice threshold.Exec finished: Sent when the task completes.Exec denied: Sent if the request is rejected.
If you are using approval-gated execs, the system reuses the approval ID as the runId in these messages, which makes correlation much easier.
Best Practices
Section titled “Best Practices”I have a few recommendations for keeping your environment secure while using these features:
- Prefer allowlists: The
fullsecurity mode is powerful. I recommend using allowlists whenever you can to limit exposure. - Use “ask” mode: This keeps you in the loop for manual verification while still allowing for fast approvals through chat.
- Isolate agents: Use per-agent allowlists. This prevents approvals meant for one agent from leaking into others.
- Understand
/exec security=full: This is a session-level convenience for authorized operators. It skips approvals by design, so use it carefully.
Troubleshooting
Section titled “Troubleshooting”Unauthorized Senders
If someone tries to run /exec and nothing happens, check their authorization. Approvals only apply to host exec requests from authorized senders. Unauthorized users cannot issue these commands.
Hard-Blocking Host Exec
If you need to completely disable host exec, you have two options. You can set approvals security to deny, or you can deny the exec tool entirely via your tool policy.
If you need help with your specific configuration, check out the AI Setup Assistant.
What’s Next
Section titled “What’s Next”OpenClaw Expert
Still stuck?
If this page didn't answer your case, ask OpenClaw Expert for step-by-step guidance.