Introduction
The Sandbox package provides a unified API for executing shell commands with controlled resource limits and configurable isolation. Whether you need to run a quick script on the host machine or execute untrusted code inside a locked-down container, Sandbox gives you a single, consistent interface backed by pluggable drivers. Every execution is governed by an immutableExecutionPolicy that defines timeout limits, memory caps, network access, environment variables, and file-system boundaries. The policy travels with the sandbox instance, ensuring that your constraints are always enforced regardless of which driver you choose.
Core Architecture
The package is built around four primary components:Sandbox
TheSandbox class is the main entry point. It accepts an ExecutionPolicy and produces a driver instance that implements the CanExecuteCommand contract. You can select a driver through static factory methods (Sandbox::host(), Sandbox::docker(), etc.) or dynamically via the SandboxDriver enum.
ExecutionPolicy
TheExecutionPolicy is an immutable configuration object that controls every aspect of command execution. Each with*() method returns a new instance, making policies safe to share and compose without side effects.
CanExecuteCommand
All drivers implement theCanExecuteCommand interface, which exposes an execute() method and a policy() accessor. This contract guarantees that you can swap drivers without changing any calling code, making it straightforward to use the host driver in development and a container driver in production.
ExecResult
Every execution returns anExecResult — a readonly value object that provides access to stdout, stderr, the exit code, wall-clock duration, and flags indicating whether the output was truncated or the command timed out.
Supported Drivers
The package ships with five drivers, each offering a different level of isolation:| Driver | Isolation | Platform | Use Case |
|---|---|---|---|
| Host | None (process-level only) | All | Development, trusted scripts |
| Docker | Full container | Linux, macOS, Windows | Production workloads, untrusted code |
| Podman | Full container (rootless) | Linux | Rootless container execution |
| Firejail | Linux namespaces + seccomp | Linux | Lightweight sandboxing without containers |
| Bubblewrap | Linux namespaces | Linux | Minimal sandbox with namespace isolation |
ExecutionPolicy constraints and return the same ExecResult type, so your application code remains driver-agnostic.
Security Defaults
The package ships with secure defaults that apply across all drivers:- Network disabled — Commands cannot reach external services unless you explicitly call
withNetwork(true). - Environment scrubbed — Security-sensitive variables (
AWS_*,LD_PRELOAD,GOOGLE_APPLICATION_CREDENTIALS, etc.) are always stripped, even when environment inheritance is enabled. - Output bounded — Both stdout and stderr are capped at 1 MB by default. When exceeded, only the most recent bytes are retained.
- Timeout enforced — Commands are terminated after 5 seconds by default. Both wall-clock and idle timeouts are supported.
- Container hardening — Docker and Podman drivers run with a read-only root filesystem, all capabilities dropped,
no-new-privilegesset, and commands execute as thenobodyuser (UID 65534).
Documentation
- Getting Started — Run your first sandboxed command in three steps.
- Execution Policy — Configure timeouts, memory, paths, environment, network, and output limits.
- Drivers — Choose and configure the right isolation backend.
- Streaming and Results — Consume output in real time and inspect execution results.
- Testing — Use
FakeSandboxfor fast, deterministic tests. - Troubleshooting — Diagnose and resolve common issues.