12 KiB
Sandbox Mode
Sandbox mode restricts what the agent process and its spawned commands can access on your filesystem and network using OS-level kernel primitives (Landlock on Linux, Seatbelt on macOS). The kernel enforces these limits for the process lifetime.
Sandbox mode is off by default.
Quick Start
# Run with workspace sandbox (read everywhere, write to CWD + temp dirs + ~/.grok/)
grok --sandbox workspace
# Read-only mode (read everywhere, write only to ~/.grok/ + temp dirs)
grok --sandbox read-only
# Most restrictive profile (read CWD + system paths, write CWD + temp dirs + ~/.grok/, no child network)
grok --sandbox strict
Built-in Profiles
| Profile | FS Read | FS Write | Child Network | Use Case |
|---|---|---|---|---|
off (default) |
Unrestricted | Unrestricted | Unrestricted | No sandbox |
workspace |
Everywhere | CWD + ~/.grok/ + /tmp + /var/tmp |
Allowed | Normal development |
devbox |
Everywhere | All top-level dirs except /data |
Allowed | Disposable dev VMs |
read-only |
Everywhere | ~/.grok/ + /tmp + /var/tmp |
Blocked¹ | Exploration, code review |
strict |
CWD + system paths | CWD + ~/.grok/ + /tmp + /var/tmp |
Blocked¹ | Untrusted code |
¹ Child-network blocking is enforced on Linux only (via seccomp). On macOS it is a no-op — these profiles do not restrict child-process network there.
To block specific files (e.g. .env or credential paths) on top of a profile, define a custom profile with a deny list — it is kernel-enforced (read + write/rename) and supports glob patterns like **/*.pem.
Profile Details
workspace -- The recommended profile for everyday development. The agent can read any file on the system (for understanding dependencies, system libraries, etc.) but can only write to the current working directory, ~/.grok/, and temp directories (/tmp, /var/tmp, plus the macOS temp dirs). Network access is allowed for tools like web_search and MCP servers.
devbox -- A reserved built-in profile for disposable development VMs. The agent can read everywhere and write to every top-level directory except /data and the virtual filesystems (/proc, /sys, /dev), including the home directory. Network access is allowed. --sandbox devbox runs the built-in profile, which shadows any [profiles.devbox] you define in sandbox.toml.
read-only -- Use when you want the agent to analyze code without modifying your project files. The agent can read everything but can only write to ~/.grok/ (needed for session persistence) and temp directories. Child-process network access is blocked on Linux (no-op on macOS).
strict -- The most restrictive profile, for reviewing untrusted code. The agent can only read files within the current working directory and essential system paths. Writes are limited to CWD, ~/.grok/, and temp directories. Child-process network access is blocked on Linux (no-op on macOS).
Custom Profiles
Create custom sandbox profiles in ~/.grok/sandbox.toml (global) or .grok/sandbox.toml (per-project):
[profiles.project]
# Start from a built-in profile, then add overrides
extends = "workspace"
restrict_network = true
# Paths the agent can read but NOT write/delete
read_only = ["/data"]
# Additional writable paths
read_write = ["/tmp/scratch"]
# Paths or globs to kernel-deny (read + write/rename, enforced; see notes below)
deny = ["/data/shared-secrets", "**/.env", "**/*.pem"]
Use the custom profile:
grok --sandbox project
A custom profile can't reuse a built-in name. --sandbox devbox always runs the built-in devbox profile, shadowing any [profiles.devbox] you define.
When the global and per-project files define the same custom profile name, the user-level definition takes precedence and the project definition is ignored. If those two definitions differ, Grok warns about the conflict at startup — on the welcome screen in the TUI, and on stderr for headless runs. Identical duplicate definitions do not produce a warning.
Custom Profile Fields
| Field | Type | Description |
|---|---|---|
extends |
String | Base built-in profile to inherit from (workspace, devbox, read-only, strict). Defaults to workspace when omitted |
restrict_network |
Boolean | Block network access for child processes |
read_only |
String[] | Additional read-only paths |
read_write |
String[] | Additional read-write paths |
deny |
String[] | Paths or globs to kernel-deny (read + write/rename; see notes). An entry with *, ?, or [ is a glob |
Note on
deny: A non-emptydenylist is kernel-enforced. Denied paths are read-denied and write/rename-denied via Seatbelt on macOS and a bwrap bind-over on Linux, so a denied path can neither be read (viabash,grep, or subagents) nor relocated out of the deny set and read elsewhere (themv secret x && cat xbypass is closed). On Linux, read-deny requiresbubblewrap: if it is missing (or any single deny path can't be bound), Grok refuses to start rather than run with denied paths exposed (devbox, which only write-denies/data, still falls back to Landlock). Writes to paths not indenyare controlled by what you grant inread_write.
Globs in
deny: An entry is a glob if it contains*,?, or[. Those characters always mean glob — to deny a literal file whose name contains them, name a parent directory instead. The supported, gitignore-style subset is:
*— any run of characters within one path segment (stops at/)?— exactly one character within a segment**— spans directories (as a whole path segment, e.g.**/,a/**);**/also matches zero directories, so**/.envmatches.envandsub/.env[abc]/[a-z]— character classes; a leading!or^negates ([!a]and[^a]both mean "nota")Brace alternation (
{a,b}), backslash-escapes, and the unusual class forms[]…](literal]first) and POSIX[[:…:]]are not supported, so the two platforms can never interpret a glob differently. A glob using an unsupported metacharacter, or one that is malformed, makes Grok refuse to start (fail closed) on both platforms — write*.pemand*.keyas separate entries rather than*.{pem,key}.Relative globs are anchored at the workspace; absolute globs (e.g.
/home/**/.ssh) at their literal prefix. Non-glob entries keep exact-path matching. Enforcement otherwise differs by platform:
- macOS is airtight: each glob becomes a Seatbelt regex applied at runtime, so matching files are denied even if created after Grok starts.
- Linux is best-effort: a mount namespace can't glob at runtime, so each glob is expanded to the files that exist at launch and those are bound over. Files created later that match a glob are not covered — name exact paths for anything that must be airtight on Linux. A glob that matches too many files, or whose tree is too deep/broad to walk, makes Grok refuse to start rather than under-enforce.
How It Works
The sandbox is applied to the entire grok process at startup using kernel primitives -- not per-command wrapping. This means all tool operations are covered:
read_file,search_replace,list_dir-- restricted by Landlock/Seatbelt in-processbashcommands,grep(rg) -- child processes inherit FS restrictions automatically- Network -- on Linux, child processes can be blocked via seccomp; on macOS this is a no-op
The sandbox is irreversible once applied. The agent cannot relax restrictions at runtime.
Resuming Sessions
The profile a session was started with is saved with the session and is fixed
for the life of the session. When you resume it (grok --resume <id>,
grok --continue, or grok -r), Grok restores that same profile automatically —
so a session started with --sandbox workspace won't silently come back under a
stricter default and break commands that previously worked.
Resuming will not change a session's sandbox:
- Omitting
--sandboxon resume uses the session's saved profile. - Passing
--sandbox <profile>that matches the saved profile is allowed. - Passing
--sandbox <profile>that differs from the saved profile is refused with an error — changing a resumed session's sandbox is a safety footgun (it could widen access the session was meant to be confined to, or break a session that relied on broader access). Start a new session to use a different profile.
Profile resolution order for a new session:
- An explicit
--sandbox <profile>flag orGROK_SANDBOXenvironment variable - The
[sandbox] profilein your config off(no sandbox)
Platform Support
| Platform | Mechanism | Minimum Version |
|---|---|---|
| Linux | Landlock | Kernel 5.13 or later |
| macOS | Seatbelt | macOS (all versions) |
If the sandbox cannot be applied (e.g., unsupported kernel, missing entitlements), Grok logs a warning and continues without enforcement. The exception is an explicitly-requested custom profile: on both macOS and Linux, if it cannot be applied (unknown profile, malformed sandbox.toml, or — on Linux — bubblewrap unavailable for a non-empty deny), Grok refuses to start rather than run with its denied paths exposed.
Network Restrictions
On Linux, profiles with restrict_network block network access in child processes (bash commands, scripts) via seccomp. On macOS, network blocking is a no-op. Built-in tools that make HTTP requests in-process (web search, LLM API calls) are never affected -- the agent needs network access to function.
In practice, on Linux this means:
web_search,web_fetch, and the LLM API always have network accessbashcommands likecurl,wget, andnpm installare blocked whenrestrict_networkis enabled
Event Logging
Sandbox events are logged to ~/.grok/sandbox-events.jsonl for debugging. Events include:
- Profile applied (which profile, timestamp)
- Violations (attempted access to denied paths)
When to Use Sandbox Mode
Use workspace when:
- Working on your own projects and you want basic write protection
- Running in shared environments where you want to limit the scope of changes
Define a custom profile with a deny list when:
- You need to block specific files (e.g.
.envor credential paths) on top of a base profile - You need kernel enforcement that covers
bash,grep, and subagents — not just theread_filetool
Use read-only when:
- Reviewing code you do not trust
- Exploring a codebase without risk of accidental modification
- Running code analysis or audits
Use strict when:
- Analyzing untrusted or third-party code
- Running in security-sensitive environments
- You want maximum isolation
Skip sandbox when:
- The agent needs to install dependencies (
npm install,pip install) - The agent needs to modify files outside the working directory
- You are working in a trusted environment and want maximum flexibility
Trade-offs
| Aspect | Without Sandbox | With Sandbox |
|---|---|---|
| Safety | Agent has full system access | Agent restricted to profile rules |
| Capability | Can do anything | Limited by profile |
| Performance | No overhead | Negligible overhead |
| Recovery | Must trust the agent | Kernel enforces boundaries |
The sandbox enforces limits at the OS level -- through Landlock or a mount namespace on Linux, and Seatbelt on macOS -- not a separate VM.