Back to Zeroclaw

The security model

docs/book/src/security/model.md

0.8.36.4 KB
Original Source

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_only is 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 list
  • forbidden_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:

PlatformDefault backend
LinuxLandlock (kernel) / Bubblewrap / Firejail / Docker, auto-detected
macOSSeatbelt (native)
WindowsAppContainer (experimental)
AnyDocker (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 estop halts 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:

toml
[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:

  1. The security validator returns an error
  2. The runtime wraps it as a ToolResult::Err and hands it back to the model
  3. 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.