For newcomers · 1 of 2
What a sandbox is
Someone hands you a program and says "run this for me". You did not write it, and you are not going to read all of it. It is probably fine. Most code is. This page is about the rest, and about how plimsoll tells you which precautions a given run actually got.
Running code you did not write
A program you run acts as you. It can read the files you can read, send what you can send over the network, and use as much memory and time as the machine will give it. That is the deal with every program on your computer, and it works because you chose those programs.
More and more code comes from nobody you chose. An AI agent, a program that uses a language model to decide what to do next, writes a few lines to answer a question and wants them run. The model may simply be wrong. It may have read a web page with instructions planted in it, a trick called prompt injection: instructions hidden in data a model reads, written so that the model follows them. Either way, the code that arrives is a stranger's code, and you are about to let it act as you.
A sandbox is a place where code runs with something stopping it from reaching the rest of the machine. Think of a room in your house set aside for a visitor: you let the stranger in, but only into that room, and the door locks from the outside. plimsoll's documentation even calls the stranger's code the guest: the code running inside a sandbox, seen from the machine that runs it.
Rooms differ in their locks, and that is the whole subject of this page. plimsoll calls the
strength of the lock the isolation tier: how strong the wall around a run is, one of
four levels, weakest first: process, container, kernel,
vm. plimsoll does not build the rooms itself. It is the doorman in front of them:
it checks each request, sends it to the one kind of room it was set up with, and writes on
every answer which kind of room that was.
Five strangers in the cheapest room
On 2026-11-05 a plimsoll server, plimsolld, was started on a laptop with the
setting SANDBOX_PROVIDER=wasm. The provider is the backend that actually
runs the code, and each server uses exactly one. wasm is the cheapest room plimsoll
has: JavaScript runs on QuickJS, a small JavaScript engine, compiled to
WebAssembly, a portable bytecode format that runs inside a host program, which decides
everything the code can reach. Here the host program is plimsolld itself.
Five short JavaScript programs were sent to it, four of them behaving the way a badly behaved stranger might, and a sixth from a careful caller. What each card shows came back from the server unedited; it is read from the signed recording published beside the next page (INTERNAL · plimsoll site →), which also shows how to check it.
1. The polite one
ran normallyWhat it sent
What came back
Most code is like this. The room exists for the other kind.
2. The one who wants the internet
stoppedWhat it sent
What came back
It looked for every usual way to open a connection: fetch,
XMLHttpRequest and WebSocket from web browsers, and
require and process from Node.js, the JavaScript runtime most servers
use. None of them exist here. No firewall is needed when the room has no telephone: the
engine is started without any function that opens a connection.
3. The one who goes through your drawers
stoppedWhat it sent
What came back
This one did its homework. QuickJS ships modules for files and folders, and the
stranger found them and asked for /etc/passwd, the file that lists a Linux machine's user
accounts. It got null: nothing to open. Then it asked for a listing of the top
folder and got an empty list with error 44, which in WASI, the standard set of system functions
a WebAssembly program can be offered, means "no such file or directory". plimsoll starts the
engine with no folders handed to it at all
(sandbox/wasm.go (EXTERNAL · source repo ↗)),
so every path is missing. The filing cabinet is there; it has no drawers.
4. The one who eats everything
stoppedWhat it sent
What came back
The engine's memory is capped at 256 MiB, and the cap is enforced by the
WebAssembly runtime underneath, not by asking nicely. Thirty-one piles of a million numbers
is about 248 million bytes (8 bytes a number); the thirty-second pile did not fit, the engine
said "out of memory", and the program's own catch printed it. plimsoll exists
partly because a popular JavaScript sandbox library once advertised a memory limit that did
nothing at all
(the story in docs/isolation-tiers.md (EXTERNAL · official docs ↗)).
5. The one who never leaves
stoppedWhat it sent
What came back
The request allowed 2 seconds ("timeoutMs": 2000). The loop promised
to run forever and was stopped at the deadline. The answer says so in two ways: the run is
marked timed out, and its exit code is 124, the number the Unix timeout command
uses for the same thing. A non-zero exit code is a normal answer in plimsoll, not an error: the
code ran, and this is how it ended.
6. The careful caller
refused, nothing ranWhat it sent
{
"protocol": 5,
"minimumIsolation": "kernel",
"javascript": {
"code": "console.log(\"hello\");\n"
}
}What came back (recorded output of plimsoll-attest)
plimsoll-attest: refused before dispatch (reason isolation), so nothing ran; the bundle is unchanged: sandbox isolation requirement not met failed_precondition: sandbox isolation requirement not met: provider isolation process is below requested minimum kernel
Not a stranger: a caller who reads the sign before going in. Its request names a
floor, the weakest isolation tier it will accept, here kernel. This room
is process, so plimsoll refused before dispatch, the handover that
starts the code. Nothing ran, and the answer is marked so, which tells the caller it is safe to
send the same request to a stronger room. Because nothing ran, there is no
run record (INTERNAL · glossary →) for it either. The request is requests/floor.json.
What this room does not stop
Every stranger above was stopped by the engine. But the engine runs inside plimsolld, the
plimsoll server's own program. A stranger who found a bug in QuickJS or in the WebAssembly
runtime could make an escape, a bug that lets code inside a sandbox act outside it,
and it would land inside plimsolld, with plimsolld's permissions. That is why this room's tier
is called process, and why plimsoll's own documentation says not to point it at
hostile code. It is for speed and for development: the first three runs above took
, and
.
These five strangers tried the obvious doors. None tried to break the engine, so this page shows the room's rules being kept, not that the engine has no bugs.
Four rooms, four locks
Each provider restricts memory, run time, files and network access. For providers whose walls depend on the host or a remote service, a startup test checks the promised restrictions; the in-process wasm provider relies on the project's own tests. (A run can be given one narrow exception, a grant: permission, attached to one run, for its code to call listed routes of one HTTP API through plimsoll, which adds the credential itself, so the code never sees it.) Where rooms differ is what happens when the lock itself has a bug. The picture puts each room where its escape would land.
The playpen
Tier process · provider wasm
- What it is
- A playpen in your living room. QuickJS runs inside plimsolld's own program, behind the walls the WebAssembly engine draws: no files, no network, a hard memory cap, a deadline.
- If the lock breaks
- The stranger is loose in your living room: inside plimsolld, with its permissions. There is no operating-system wall at all.
- Runs
- One JavaScript snippet at a time. No files, packages or build steps.
- For hostile code?
- no Fast and free, for code you mostly trust.
The spare room
Tier container · providers docker under runc, openshell, agentsandbox under runc
- What it is
- A spare room with its own lock, sharing the house's wiring. A container is a process started with its own view of files, network and other processes, while still sharing the machine's kernel. Docker's default runtime, runc, builds those walls with the kernel's own features. plimsoll's docker room adds a read-only root, small writable areas held in memory where a written file cannot be started as a program by its path, no network but the container's own loopback (a connection only to itself), and root's special powers taken away.
- If the lock breaks
- The stranger talks to the shared kernel directly, so a bug in the Linux kernel is a way into the whole house.
- Runs
- Snippets and whole projects with files and build steps; compiled simulators on the docker provider only.
- For hostile code?
- no, not alone Solid hardening, but standing on a shared foundation.
The spare room with a receptionist
Tier kernel · providers docker under runsc, once checked, agentsandbox under runsc
- What it is
- The same room, with someone at the door who takes every request. gVisor is Google's open-source stand-in kernel, written in Go (the programming language) and running as an ordinary program, that handles almost every request a container's code makes itself and uses only a short, locked-down list of real kernel calls. Docker starts a container under it through gVisor's runtime, runsc: the program docker calls instead of runc.
- If the lock breaks
- The stranger has to get past gVisor and then through the short list of calls gVisor still makes. Two bugs, in a row, and it is still your house.
- Runs
- The same as the spare room (compiled simulators on docker only), a little slower to start.
- For hostile code?
- yes The weakest room plimsoll calls good enough for hostile code on your own machine, when its startup check passes.
The cabin across town
Tier vm · providers e2b, dockercloud, agentsandbox under kata
- What it is
- A whole separate small computer. A microVM is a small virtual machine with its own kernel, started for one run and destroyed after it, kept apart from its neighbors by the processor itself. E2B and Docker Cloud Sandboxes are hosted services that rent them out by the second.
- If the lock breaks
- The stranger is in a throwaway machine with its own wiring. To go further it must break the hypervisor, the program that runs virtual machines and keeps them apart. On a hosted service, that machine is not yours.
- Runs
- Snippets and whole projects. Hosted E2B and Docker Cloud Sandboxes bill by the second; a Kata cluster you run yourself has infrastructure costs, without a plimsoll fee per run.
- For hostile code?
- yes The strongest wall plimsoll reports, still a statement from its checks rather than independent proof from the machine itself. A hosting company can read what it runs, so keep secrets out of the image.
There is a fifth setting, and it is the default: no room at all. With
SANDBOX_PROVIDER unset, plimsoll runs nothing and says so. The front door stays
bricked up until somebody chooses a room on purpose.
The other rooms are not drawn from imagination. On 2026-09-28 the same program, one that balances a simulated pole on a cart, was sent to five rooms with nothing changed but the provider setting, and each answer stated its room. One of them was a sandbox from OpenShell, NVIDIA OpenShell, an agent sandbox runtime whose gateway server creates and deletes sandboxes on request (same run, different sandboxes (INTERNAL · plimsoll site →)):
| Room | Where it ran | Tier the answer stated |
|---|---|---|
| Docker, locked down (runc) | the same machine | container |
| Docker with gVisor (runsc) | the same machine | kernel |
| NVIDIA OpenShell sandbox | an OpenShell gateway, docker inside | container |
| E2B microVM | E2B's cloud | vm |
| Docker Cloud Sandboxes microVM | Docker's cloud | vm |
All five produced the same result, byte for byte. The process room was not in that recording: it runs single snippets, and that program is a project with several files.
The sign on the door
Every answer above says process. Where does that word come from? Not from an
inspector. It is plimsoll's statement, assembled from what it can check, and it is worth knowing
exactly what goes into it.
Think of a hotel. The hotel set the room up, checked at opening time that the deadbolt turns and the window does not open, and prints "deadbolt" on your bill. That is worth a good deal more than a brochure. It is still the hotel's word: nobody from outside inspected the lock this morning, and nothing on the bill would change if someone swapped the lock after opening time.
The exact term for the inspector's certificate is attestation: cryptographic proof, usually rooted in the hardware, of exactly what software a machine is running. plimsoll does not have it, and says so wherever it reports a tier. Concretely:
- kernel on docker rests on docker's own registration of the
runscruntime, checked by the preflight (the configuration check a provider runs at startup and on each readiness poll), plus the smoke test. The code says in so many words that this is not proof that the wall actually running is gVisor (sandbox/docker_preflight.go (EXTERNAL · source repo ↗)). - vm on E2B and Docker Cloud Sandboxes follows from which service it is. Their smoke tests prove the microVM behaves as promised, network blocked included; they do not prove a hypervisor is there.
- process, the runs on this page, has no smoke test at all, because its walls are library code built into plimsolld and the same on every machine. The project's own tests prove the memory cap and the missing network functions, and at startup the wasm provider only reads its settings.
- If the machine is changed after startup, or plimsolld itself is taken over, the sign can be wrong. A compromised server can state anything.
The full account, provider by provider, is docs/isolation-tiers.md (EXTERNAL · official docs ↗). If the attacks you must hold out against need attestation, no room here supplies it.
What you can do with the sign
Read it, and refuse to go in below the room you need. A request can name its floor, as the
careful caller above did, and anything weaker is refused before a single line runs. The operator
can set a floor for the whole server (SANDBOX_MIN_ISOLATION), and plimsoll's
hardened mode, the startup setting PLIMSOLL_HARDENED=1, refuses to start
unless every production safeguard is configured and refuses any run below kernel.
The official clients also compare the tier that comes back with the floor that went out.
What this page does not show
- The other rooms, tonight. Only the process room ran for this page. The other rooms' tiers come from the 2026-09-28 recording linked above.
- That the code's answer is right. A sandbox limits what wrong code can damage. It does nothing to make a wrong answer right.
- An attack on the engine. The strangers tried the doors, not the hinges.
- Proof of the room. Every tier here is plimsoll's statement from its settings and its checks, never attestation.
Next: the receipt
Every answer above came with a run record (INTERNAL · glossary →), plimsoll's written statement of what was sent, what came back and which room ran it, and the five were signed into one file as they came back. The next page shows what is on a run record, why the client checks it, who signs it and what it cannot prove, and lets you check these five in your browser.
- Proof of what ran (INTERNAL · plimsoll site →): the signed records of the five runs on this page.
- Plain English (INTERNAL · trainer site →): the same walls as an interactive cross-section, and the words decoded.
- Concepts: read the mark, not the name (INTERNAL · trainer site →): each tier with its real checks.
- What plimsoll does not do (EXTERNAL · official docs ↗): the limits, stated plainly.