The security model
ZeroClaw’s security model gates what the agent is allowed to do at runtime. There are six layers. From outer to inner:
Channel pairing and access control
Before a message from a channel reaches the agent, the channel’s pairing and allow-list are checked. allowed_users, allowed_chats, IP allowlists for webhooks, all enforced at the channel adapter, before the runtime sees the event.
Docs: each channel’s page under Channels.
Autonomy level
The coarse-grained knob. Three settings:
- ReadOnly: the agent can observe (read files, query memory, fetch URLs it’s allowed to fetch) but cannot write or execute commands.
- Supervised (default): low-risk ops run; medium-risk ask the operator; high-risk block.
- Full: no approval gates;
workspace_onlyis implicitly disabled.forbidden_paths,forbidden_commands, and the OS sandbox still enforce.
Docs: Autonomy levels.
Workspace boundary and path rules
The agent operates within a configured workspace directory. file_read, file_write, and shell (for commands that touch the filesystem) refuse paths outside it unless workspace_only = false.
Per-session sandbox roots (ACP and gateway WebSocket): When a session is opened via ACP (session/new with a cwd parameter) or via the gateway WebSocket (connect-time cwd parameter), that path becomes the SecurityPolicy workspace boundary for all file and shell tools for the lifetime of the session. The daemon’s global workspace_dir remains the data directory for memory, identity, cron, and other persistent state. The model is: session cwd = project boundary the agent can touch; workspace_dir = where ZeroClaw stores its own files. Note: the agent’s system prompt currently reflects the daemon’s workspace_dir rather than the session cwd; enforcement is correct but the model’s self-reported location may differ.
Important: the cwd parameter changes which directory on the ZeroClaw host the agent is sandboxed to, it does not affect which machine tools run on. Tool use (shell commands, file reads/writes) always executes on the machine running ZeroClaw. If you connect to a remote ZeroClaw instance over the gateway WebSocket, tool calls operate on the remote machine’s filesystem, not on your local machine. For localhost-only deployments this distinction does not matter, but remote setups should account for it.
Beyond the workspace, a forbidden_paths list (default: /etc, /sys, /boot, ~/.ssh, …) is always blocked regardless of workspace setting.
Shell command policy
For shell invocations:
allowed_commands: if non-empty, shell only runs commands whose basename is in this listforbidden_commands: explicit denylist (rm -rf /,shutdown, kernel operations)validate_command_execution: a pattern-matching pass that looks for dangerous flags, pipelines, and argument shapes
The validator runs before the command hits the shell. A blocked command surfaces as a tool error the model sees and can react to.
OS-level sandbox
When a sandbox backend is available, tool invocations run inside it:
| Platform | Default backend |
|---|---|
| Linux | Landlock (kernel) / Bubblewrap / Firejail / Docker, auto-detected |
| macOS | Seatbelt (native) |
| Windows | AppContainer (experimental) |
| Any | Docker (if the daemon is reachable) |
The sandbox confines filesystem access to the workspace, drops network reachability except what the tool explicitly needs, and removes access to the parent process’s secrets.
Docs: Sandboxing.
Tool receipts
Tool receipts provide HMAC evidence that a successful tool call and its result passed through the runtime. When receipts are enabled, successful tool outputs receive an HMAC-SHA256 receipt over the call and result, and the receipt is fed back into the conversation with the tool result.
Receipts help catch fabricated tool claims. They are not a chained or durable audit log today: receipt keys are ephemeral, receipts are not cross-signed with the conversation hash, and persistent receipt storage is still future work.
Docs: Tool receipts.
Additional gates
Beyond the six layers:
- OTP gating:
[security.otp] gated_actions = ["shell", "browser", "file_write"]requires a one-time code before each listed action. Useful for remote-access scenarios. - Emergency stop:
zeroclaw estophalts all in-flight tool calls. With[security.estop] enabled = true, resuming requires an OTP. - Prompt injection guard: scans model output for known injection patterns before tool calls are validated.
- Leak detector: scans outbound channel responses for credentials and redacts matches before delivery. It covers deterministic credential patterns and can also run a standalone high-entropy-token heuristic.
- Pairing guard: device pairing for channel auth; prevents stolen credentials from working on a new device.
Leak detector configuration
Configure outbound leak detection in its own TOML section:
[security.leak_detection]
enabled = true
sensitivity = 0.7
high_entropy_tokens = true
enabled = false disables the entire outbound leak detector.
high_entropy_tokens = false disables only the standalone entropy heuristic;
deterministic credential patterns still run. sensitivity accepts 0.0
through 1.0; higher values are more aggressive.
The complete field table and defaults are in the Config reference.
When things go wrong
A blocked tool call doesn’t silently fail:
- The security validator returns an error
- The runtime wraps it as a
ToolResult::Errand hands it back to the model - The model sees “Error: Shell command blocked by policy: forbidden pattern
rm -rf /” and can retry, apologise, or ask the user
If a tool is excluded from the channel via [autonomy].non_cli_excluded_tools (which gates non-CLI channels as a group), it simply isn’t advertised to the model on those channels. Model never sees a tool it can’t use.
Default posture
Out of the box:
- Autonomy:
Supervised - Workspace-only:
true - Sandbox: auto-detect (uses whatever the OS provides)
- Audit logging:
false(enable explicitly) - OTP:
false - E-stop:
false
This is a reasonable middle ground, safe enough for a laptop, permissive enough to not frustrate. Crank it up for production (OTP, audit, restricted tools) or down to YOLO for a dev box.