Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

sandtrace run

Executes untrusted binaries inside an 8-layer isolation sandbox with ptrace-based syscall tracing.

Usage

sandtrace run --trace-only -vv /bin/ls /tmp                   # Trace only (no enforcement)
sandtrace run --allow-path ./project --output trace.jsonl npm install  # With filesystem restriction
sandtrace run --policy policies/strict.toml ./untrusted        # Custom policy
sandtrace run --allow-net curl https://example.com             # Allow network

Flags

FlagDefaultDescription
--policyTOML policy file
--allow-pathAllow filesystem access to path (repeatable)
--allow-netfalseAllow network access
--allow-execfalseAccepted by the CLI; reserved for future child execution controls
-o, --outputJSONL output file
--timeout30Kill process after N seconds
--trace-onlyfalseDisable enforcement (no Landlock/seccomp)
--follow-forkstrueTrace child processes (enabled by default)
--no-colorfalseDisable colored output
-v / -vv / -vvvVerbosity level

Sandbox layers

Applied in order after fork():

LayerMechanismWhat it does
1User namespaceGain capabilities without privilege escalation
2Mount namespaceRestrict filesystem view
3PID namespaceHide host processes
4Network namespaceIsolate network (unless --allow-net)
5PR_SET_NO_NEW_PRIVSPrevent privilege escalation via setuid
6Landlock LSMKernel-level filesystem access control
7seccomp-bpfBlock dangerous syscalls at kernel level
8ptrace TRACEMESignal readiness to tracer, raise SIGSTOP

Layers 6-7 are skipped when --trace-only is set.

Always-blocked syscalls

The following syscalls are always blocked by the seccomp-bpf filter, regardless of policy:

kexec_load, kexec_file_load, reboot, swapon, swapoff, init_module, finit_module, delete_module, acct, pivot_root

JSONL output format

When using --output, each line is a self-contained JSON object:

Syscall event

{
  "event_type": "syscall",
  "timestamp": "2025-01-01T12:00:00Z",
  "pid": 1234,
  "syscall": "openat",
  "syscall_nr": 257,
  "args": {"raw": [0, 140234567, 0, 0, 0, 0]},
  "return_value": 3,
  "success": true,
  "duration_us": 42,
  "action": "allow",
  "category": "file_read"
}

Process lifecycle

{"event_type": "process", "kind": "spawned", "timestamp": "2025-01-01T12:00:00Z", "parent_pid": 1234, "child_pid": 1235}
{"event_type": "process", "kind": "exited", "timestamp": "2025-01-01T12:00:01Z", "pid": 1234, "exit_code": 0}

Trace summary

{"event_type": "summary", "timestamp": "2025-01-01T12:00:01Z", "total_syscalls": 4521, "unique_syscalls": 23, "denied_count": 2, "process_count": 3, "duration_ms": 1200, "exit_code": 0}

Examples

Trace a command without enforcement

sandtrace run --trace-only -vv /bin/ls /tmp

Useful for understanding what syscalls a binary makes before writing a policy.

Sandbox npm install

sandtrace run --allow-path ./my-project --output npm-trace.jsonl npm install

Restricts filesystem access to the project directory, traces all syscalls, and writes results to a JSONL file for analysis.

Use a policy file

sandtrace run --policy examples/strict.toml ./untrusted-binary

See Policies for the TOML policy format and example policies.