Skip to content

Sandbox Overview

runok can execute allowed commands inside a sandbox that restricts file system writes and network access. Sandboxing is applied at the OS level using platform-native mechanisms (macOS Seatbelt or Linux Landlock + seccomp), so sandboxed processes cannot bypass the restrictions.

See Security Model for trust boundaries and design rationale.

Sandbox policies are defined as named presets under definitions.sandbox in your runok.yml:

definitions:
sandbox:
restricted:
fs:
writable:
- '.'
deny:
- '.git'
- '.runok'
network:
allow: false

Each preset contains two sections:

FieldTypeDescription
writablestring[]Directories the sandboxed process can write to. Paths support ~ expansion.
denystring[]Paths the sandboxed process cannot write to, even within writable directories. Supports glob patterns (*, **, ?, [...], {a,b}) and <path:name> references.

The deny list always takes priority over writable. For example, if writable includes "." (the current directory) and deny includes ".git", the process can write anywhere in the project except the .git directory.

FieldTypeDescription
allowboolWhether the sandboxed process can make network connections. Defaults to true if omitted.

When network.allow is false, TCP/UDP sockets are blocked. Unix domain sockets (used for local IPC) are always permitted regardless of this setting.

You can define reusable path lists under definitions.paths and reference them in sandbox deny lists:

definitions:
paths:
sensitive:
- '.env*'
- '~/.ssh/**'
sandbox:
restricted:
fs:
deny:
- '<path:sensitive>'

The <path:sensitive> reference expands to all paths listed under definitions.paths.sensitive. See Path References and definitions.paths for details.

Attach a sandbox preset to any allow or ask rule with the sandbox field:

rules:
- allow: 'python3 *'
sandbox: restricted
- allow: 'npm test'
sandbox: restricted

Use defaults.sandbox to apply a sandbox preset to all rules that do not specify one explicitly:

defaults:
sandbox: restricted
rules:
- allow: 'git status' # uses "restricted" sandbox
- allow: 'cargo build *'
sandbox: build-env # overrides with "build-env"

When a compound command like sh -c "cmd1 && cmd2" is evaluated, each sub-command may match a different sandbox preset. runok merges all matched policies using the Strictest Wins rule:

FieldMerge strategyEffect
writableIntersectionOnly directories allowed by all policies remain writable
denyUnionDenied paths from any policy are protected
network.allowANDNetwork is blocked if any policy denies it

This ensures that a less-restricted command in a pipeline cannot weaken the restrictions of a more-restricted command.

If the intersection of writable roots becomes empty (a contradiction), runok escalates the action to ask so the user can decide whether to proceed.

definitions:
paths:
sensitive:
- '.env*'
- '~/.ssh/**'
- 'credentials.*'
sandbox:
workspace-write:
fs:
writable:
- '.'
deny:
- '.git'
- '.runok'
- '<path:sensitive>'
network:
allow: true
no-network:
fs:
writable:
- '.'
deny:
- '.git'
- '.runok'
network:
allow: false
defaults:
sandbox: workspace-write
rules:
- allow: 'git *'
- allow: 'python3 *'
sandbox: no-network
- allow: 'npm test'
sandbox: no-network
- deny: 'rm -rf /'