Rust · safe sandbox for AI agents
Cocoon is a safe code-execution sandbox for AI agents, and a rootless Linux container runtime you can read end to end. Give it a command, get back a structured Outcome: exit code, output, wall time, peak memory. Edit a bundle config and press Launch to watch the real isolation sequence, namespaces, pivot_root, dropped capabilities, seccomp, then the measured result an agent receives. No daemon, no root, one small binary that also speaks MCP.
Edit the cocoon.conf bundle on the left, or pick a preset chip, then press Launch container to watch the isolation sequence play out: new namespaces, pivot_root, dropped capabilities, and the seccomp filter. Drag the timeline slider to step through it tick by tick, and read the measured Outcome an agent would receive at the end.
runs fully client-side, the same config parser and planner as the CLI, nothing leaves the page
The sandbox runs the bundle and hands back the exact result an agent parses: exit code, captured output, wall time, and peak memory, on one line.
a chatty program never deadlocks: output is drained through pipes as the process runs, and a timeout kills an overrun and reports timed_out: true
An agent that runs code it just wrote needs isolation, a timeout, metering, and a result it can parse. The usual options sit on either side of that gap. This is an honest positioning, not a benchmark.
Needs a daemon and a root-ish setup, ships an image format and layers, and is heavy to embed next to an agent.
Bare isolation CLIs. They give you a namespace but no timeout, no metering, and no structured result, so you script that part yourself.
Stronger isolation, but heavyweight, and a lot to stand up just to run one command and read its output.
The small gap in the middle: give it a command, get back a JSON Outcome. Rootless, no daemon, no image format, one small binary you drop next to your agent, and it speaks MCP. Not a drop-in for runc, and it says so.
what actually isolates the process
The whole isolation sequence lives in one file, src/exec_linux.rs. These are the pieces it composes, all without root.
Maps your outer uid and gid to 0 inside the new user namespace. This is the move that lets everything below run with no sudo and no real privilege.
Makes the mount tree private, pivot_roots into the bundle rootfs, mounts a fresh /proc, binds a minimal /dev, and drops the old root.
The forked child is pid 1 in a new pid namespace and sees only its own processes, not the host's hundreds.
Its own hostname, set inside the container, independent of the host's.
Isolates System V IPC and POSIX message queues so the process cannot reach the host's.
The ambient set is cleared and the whole capability bounding set is dropped, so the code runs with an empty effective set (CapEff is 0) and cannot regain privilege.
Set before exec so a setuid binary or file capabilities can never raise privilege for the child or anything it spawns.
A curated deny-list returns EPERM for dangerous syscalls, including the whole mount family and pivot_root, so a read-only mount cannot be re-opened from inside.
scripts/prove.sh builds a busybox rootfs, runs a container as an ordinary user, and checks what the process inside sees. This runs in CI on every push.
# host is 'kali' at uid 1000. inside the container: container said: host=cocoonbox pid=1 uid=0 procs=4 isolation: only 4 process(es) visible in the pid namespace (host has hundreds) PROOF OK: rootless isolation verified # and the hardening, checked inside a running container: NoNewPrivs: 1 # cannot regain privilege Seccomp: 2 # a seccomp filter is loaded
Different hostname, pid 1, uid 0 mapped from your real uid with no privilege used, its own filesystem and process view, capabilities dropped and a seccomp filter loaded. The whole runtime is one file, src/exec_linux.rs.
One small binary with a handful of subcommands, a structured result, an MCP server, and a dependency-free core you can call as a library.
spec writes a bundle skeleton, plan shows what a run will do on any OS, run forwards the exit code, exec runs it and returns the measured result.
The full Outcome on one line: exit_code, stdout, stderr, wall_ms, peak_mem_kib, and the timed_out and oom_killed flags, ready for a caller to parse.
cocoon mcp speaks JSON-RPC 2.0 over stdio and exposes one tool, run_in_sandbox, so Claude and other agents call the sandbox directly.
strict for untrusted code (network off, read-only base, 5s, 128 MiB) and build for artifacts (writable, 5m, 1 GiB); any explicit key still wins.
The config, plan, and lifecycle core is dependency-free and portable, so it builds and tests anywhere, including macOS, with the Linux isolation pulled in only on Linux.
# the portable core builds and tests anywhere, including macOS cargo test # make a bundle skeleton, inspect the plan, run the container (Linux) cocoon spec mybox cocoon plan mybox # works on any OS cocoon run mybox # Linux only, no root