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 normally

What it sent

What came back

Most code is like this. The room exists for the other kind.

2. The one who wants the internet

stopped

What 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

stopped

What 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

stopped

What 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

stopped

What 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 ran

What 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.

Four rooms, drawn as places in and around your house Your machine is a house. Inside it: plimsolld's own program with a playpen in it, the process room; a spare room that talks to the house's wiring directly, the container room; and the same spare room with a receptionist, gVisor, between the stranger and the wiring, the kernel room. Outside, on someone else's machine, a cabin with its own wiring, the vm room. A red dot marks the stranger's code in each. YOUR MACHINE (the house) the Linux kernel: the house's wiring, shared by every room plimsolld's own program (your living room) playpen: the wasm engine process an escape lands in plimsolld itself a container (a spare room with its own lock) container talks to the wiring directly a container under gVisor (plus a receptionist) gVisor answers almost every request kernel a short, fixed list of calls reaches the wiring SOMEONE ELSE'S MACHINE (across town) a rented cabin: a small virtual machine with its own kernel (its own wiring), made for one run and destroyed after it vm Four rooms, drawn as places in and around your house The same picture stacked for a narrow screen: inside the house, the process, container and kernel rooms, each with its path to the shared wiring; below, the vm cabin on someone else's machine. YOUR MACHINE (the house) the Linux kernel: the house's wiring plimsolld's own program (your living room) playpen: the wasm engine process an escape lands in plimsolld itself a container (a spare room with its own lock) container talks to the wiring directly a container under gVisor (plus a receptionist) gVisor answers almost every request kernel a short, fixed list of calls reaches the wiring SOMEONE ELSE'S MACHINE (across town) vm a rented cabin: a small virtual machine with its own kernel (its own wiring), made for one run and destroyed after it
The red dot is the stranger's code. The thinner the path from it to the house's wiring, the more an escape has to break. The cabin can also be on your own machines: a Kubernetes cluster (software that runs containers across machines) running Kata Containers (INTERNAL · glossary →) makes the same kind of small virtual machine for each sandbox.

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 →)):

RoomWhere it ranTier the answer stated
Docker, locked down (runc)the same machinecontainer
Docker with gVisor (runsc)the same machinekernel
NVIDIA OpenShell sandboxan OpenShell gateway, docker insidecontainer
E2B microVME2B's cloudvm
Docker Cloud Sandboxes microVMDocker's cloudvm

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.

What the tier on an answer is made of Three boxes feed the sign on the door: the operator's settings, the provider's own word, and a startup smoke test that tries a throwaway room from inside. They produce the line "isolation: kernel" printed on every answer. A fourth box, attestation, is greyed out: plimsoll does not supply it. 1 · The settings what the operator chose: SANDBOX_PROVIDER=docker SANDBOX_DOCKER_RUNTIME=runsc 2 · The provider's word at startup and on every readiness poll, docker's own list of runtimes is read: runsc is registered there 3 · The startup smoke test a throwaway room is opened once and tried from inside: the root is read-only, writes land only where promised, loopback is the only network, the process limit is the one asked for. Fail, and nothing is served. printed on every answer isolation: kernel not in it: attestation a cryptographic proof, rooted in the hardware, of what software is running now
The example is the kernel tier on docker. Each provider has its own startup checks; the e2b and dockercloud providers each open a real microVM at startup and check, among other things, that it cannot reach the internet.

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:

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

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.