Home
Why Sandlock
How It Works Use Cases Comparison Security Model
Docs
Documentation Home Getting Started CLI Reference Python SDK Sandbox Reference
Products
Overview Sandbox HTTP API Sandbox Scheduler
GitHub Schedule a Demo
Landlock · seccomp-bpf · seccomp notify

Run Untrusted Code Without Handing It Your Machine

Sandlock is a lightweight Linux process sandbox. It confines a command's filesystem, network, syscalls, and resources with kernel-enforced policy, in about 5 milliseconds. No root. No image build. No container runtime. No hypervisor.

Confine a Python agent
# Read-only system dirs, one writable dir, 512 MB cap,
# and exactly one host reachable on exactly one port.
$ sandlock run -r /usr -r /lib -r /etc -w /tmp \
    -m 512M -P 20 -t 300 \
    --net-allow api.openai.com:443 \
    -- python3 agent.py
5 ms Startup overhead 44× faster to start than Docker
0 Privileges required No root, no setuid, no daemon
97% Of bare-metal throughput Measured on Redis SET and GET

Open source, Apache-2.0, written in Rust

Kernel-enforced policy
No namespaces or cgroups
CLI, Python, Rust, Go
OCI runtime for Kubernetes
Programmable interception
The gap

Strict Confinement Without the Weight

Containers and microVMs are powerful, but both were designed to package and boot a system. When all you need is to run one command you do not trust, they make you pay for a system anyway.

Containers

Require an image build, a runtime daemon, and root or a configured user-namespace setup. Every container shares the host kernel, and the isolation boundary is a namespace, not a policy the kernel evaluates per access.

~200 ms to start
Image build in the loop
No HTTP-level control

MicroVMs

A separate guest kernel gives a strong boundary, but it needs KVM, a guest image, and a device model. Nested virtualization inside a cloud VM adds real overhead, and there is no visibility into what the guest is doing at the syscall level.

Requires KVM access
Guest image to maintain
Block-level filesystem only

Sandlock

A policy applied to a process. Landlock and seccomp-bpf enforce filesystem, network, IPC, and syscall rules in the kernel; a userspace supervisor adds resource limits, destination IP checks, HTTP method and path rules, and copy-on-write writes.

~5 ms to start, no image
Runs as an ordinary user
Method + host + path ACL
Capabilities

One Policy, Six Enforcement Surfaces

Every dimension of the sandbox is described in the same policy object, whether you write it as CLI flags, a TOML profile, or a struct in Python, Rust, or Go.

Filesystem

Landlock grants read and write paths as recursive rules the kernel evaluates on every access, so the policy is immune to time-of-check/time-of-use races. Denied paths override broader grants.

Network

Default-deny egress. Allow a hostname, an IP, or a CIDR on specific ports over TCP, UDP, or ICMP, or invert it with a denylist. Bind ports are governed separately, and can be virtualized per sandbox.

HTTP ACL

Go past host:443: allow POST api.openai.com/v1/chat/completions and nothing else. Zero-config HTTPS interception generates an ephemeral CA and splices it into the trust bundles you name.

Credential injection

The API key lives in the supervisor and is attached to the request in the proxy, strictly after the ACL check. The sandboxed process never holds the secret and cannot exfiltrate it.

Copy-on-write

Writes under the working directory are staged in an upper layer and committed on success or discarded on failure. --dry-run shows exactly which files a command would add, modify, or delete.

Resources

Memory, process count, open files, CPU percentage, disk quota, CPU pinning, and GPU device selection, all without cgroups. A given GPU index is a hard Landlock boundary, not an environment variable.

How it works

Kernel First, Supervisor Second

Sandlock forks, installs confinement in the child before it executes anything, and only then lets the workload start. What the kernel can enforce, the kernel enforces.

Landlock

Unprivileged, kernel-evaluated access control for filesystem paths, TCP connect and bind ports, and IPC scoping. Applied once and irreversible for the lifetime of the process tree.

seccomp-bpf

A default blocklist removes syscall families a confined workload has no business using. Extra denials compose on top; the blocklist itself is always applied.

seccomp notify

The supervisor sees selected syscalls before they run: destination IP checks, memory and process accounting, COW interception, /proc virtualization, and port remapping.

Programmable

A Sandbox You Can Program, Not Just Configure

Every policy on this page is declarative. Handlers are the layer underneath: your own code runs inside the supervisor, registered on any syscall you choose, and decides what the workload actually observes.

Deny, or fabricate a result. Return an errno, or a value the syscall never produced.
Serve files that do not exist. Hand the guest a sealed in-memory file: a generated config, a secret, an object fetched from storage. No host filesystem involved.
Do slow work without stalling. Defer a call to a worker, park the guest, and answer when your backend replies.
Audit that the guest cannot evade. Interception sits below the language runtime, so ctypes and raw syscalls do not route around it.
Extend confinement, never weaken it. Built-ins always run first, and registering on a blocklisted syscall is rejected before fork.
Audit every open, from your own code
import sandlock
from sandlock.handler import Handler, NotifAction

class Audit(Handler):
    def handle(self, ctx):
        # Runs in the supervisor, before the kernel acts.
        print(f"open {ctx.read_path()} from pid {ctx.pid}")
        return NotifAction.continue_()   # fall through

sb = sandlock.Sandbox(fs_readable=["/usr", "/lib", "/etc"])
sb.run_with_handlers(
    cmd=["python3", "task.py"],
    handlers=[("openat", Audit())],
)
Performance

Confinement You Can Leave On

Landlock and the seccomp blocklist cost nothing per syscall once installed. Only the syscalls the supervisor explicitly registers for take a userspace round trip.

Workload Bare metal Sandlock Docker
/bin/echo startup 2 ms 7 ms 307 ms
Redis SET, 100K ops 82K rps 80K rps 52K rps
Redis GET, 100K ops 79K rps 77K rps 53K rps
Redis p99 latency 0.5 ms 0.6 ms 1.5 ms
COW fork × 1000 No equivalent 530 ms No equivalent

Measured on a typical Linux workstation. Redis under Sandlock holds 97.1% of bare-metal throughput. COW fork produces roughly 1,900 forks per second, or 530 µs per clone.

Where teams use it

Built for Code You Did Not Write

AI agents and tool use

Give an agent a workspace, one API endpoint, and nothing else. Credential injection keeps the key out of the agent's reach, and a policy callback can revoke network access the moment the agent finishes starting up.

Read more

CI and untrusted builds

Run a pull request's build steps with the source tree copy-on-write, the network closed, and a memory cap, on a shared runner with no root and no Docker socket to hand out.

Read more

Per-request code execution

Notebook backends, code interpreters, function platforms, and grading systems that start a fresh sandbox per request. At 5 ms there is no warm pool to keep resident and nothing carries over.

Read more

Start Confining in Under Five Minutes

Sandlock is Apache-2.0 licensed, free at any scale, and builds from source with Cargo. When you outgrow one machine, the Sandbox HTTP API and Sandbox Scheduler run it as a fleet.