We Reverse-Engineered Docker Sandbox's Undocumented MicroVM API
- title
- We Reverse-Engineered Docker Sandbox's Undocumented MicroVM API
- type
- summary
- summary
- Rivet's writeup of the undocumented
/vmHTTP API in Docker's sandboxd daemon, what it gives you, and the Sandbox Agent SDK they built on top - tags
- microvm, docker, sandboxing, ai-agents, reverse-engineering
- parent
- microvm-2026
- sources
- rivet-docker-sandbox-microvm
- created
- 2026-05-22
- updated
- 2026-05-22
Rivet (rivet.dev) reverse-engineered the undocumented HTTP API behind Docker Sandboxes' microVM mode and built an open-source SDK on top โ the sandbox-agent-sdk. The post documents the API surface, shows how to create and talk to a microVM from a shell, and frames the bet: this might be the unified microVM-management surface that Docker did for containers a decade ago.
This is the operational follow-up to microvm-2026, which named Docker Sandboxes in the platform survey but couldn't yet describe the API.
What Docker Sandboxes actually is
docker sandbox run claude ~/project looks like docker run but uses completely different technology underneath. Each invocation spins up a microVM with a separate kernel โ not a container in the host kernel โ so an AI coding agent can be handed --dangerously-skip-permissions without putting the host at risk. See microvm for the architectural rationale and matryoshka-isolation for the dominant containers-in-VMs sandwich pattern.
The CLI is restricted to Docker's six whitelisted agents (Claude, Codex, Gemini, Copilot, Kiro, Cagent). Everything else has to go through the undocumented API.
| Docker Container | Docker Sandbox | |
|---|---|---|
| Security | Shared kernel (namespaces) | Separate kernel (microVM) |
| Untrusted code | Not safe | Safe |
| Network access | Direct HTTP | Via filtering proxy |
| Volumes | Direct mount | Bidirectional file sync |
| Platform | Linux, macOS, Windows | macOS, Windows only |
Linux isn't supported because Docker Desktop uses platform-specific virtualization there (Apple Virtualization.framework on macOS, Hyper-V on Windows). Nested virtualization is required. Docker Desktop 4.58+.
The /vm API surface
sandboxd listens on ~/.docker/sandboxes/sandboxd.sock with three endpoints:
GET /vmโ list all VMsPOST /vmโ create a VMDELETE /vm/{vm_name}โ destroy a VM
Create:
curl -X POST --unix-socket ~/.docker/sandboxes/sandboxd.sock \
http://localhost/vm \
-H "Content-Type: application/json" \
-d '{"agent_name": "my-sandbox", "workspace_dir": "/path/to/project"}'
Response includes vm_config.socketPath, fileSharingDirectories, stateDir, and ca_cert_path (the MITM proxy CA). VM name follows {agent_name}-vm.
The clever isolation move
The crucial structural difference from regular Docker: each microVM gets its own Docker daemon at ~/.docker/sandboxes/vm/<name>/docker.sock. The usual /var/run/docker.sock model is shared โ anyone with socket access controls every container. Sandboxes invert that: containers run normally inside the microVM and are completely isolated from the host and from other VMs.
Once you have the per-VM socket, the rest is just plain Docker:
# Build on host
docker build -t my-image:latest .
# Archive image
docker save my-image:latest > /tmp/image.tar
# Load into microVM
docker --host "unix://$VM_SOCK" load < /tmp/image.tar
# Run inside
docker --host "unix://$VM_SOCK" run -d my-image:latest
Networking is a forced MITM proxy
Outbound traffic from inside the microVM routes through a filtering proxy at host.docker.internal:3128. The proxy does man-in-the-middle on HTTPS for policy enforcement โ meaning containers either trust the proxy's CA (ca_cert_path from the create response) or set NODE_TLS_REJECT_UNAUTHORIZED=0 for prototyping. This is essentially sandboxing-ai-agents Layer 3 (HTTP policy) baked into the substrate; you can't run containers inside a sandbox without going through it.
Volumes work because the workspace syncs at the same absolute path on both sides โ so a host bind mount /Users/me/project:/Users/me/project just works.
Why this matters
Three observations from the writeup, all of which slot into existing wiki framings:
- Docker is building the unified microVM surface. Just like containers in the 2013-2015 era, microVM tooling today is fragmented across Firecracker, Cloud Hypervisor, Kata, libkrun, and platform-specific options. Docker shipping a CLI + HTTP API behind one consistent socket is the same play that turned LXC plumbing into the developer-facing
docker run. See microvm-2026 for the "this is microVMs' Docker moment" thesis the writeup is implicitly betting on. - The whitelist is the constraint. The undocumented API is the entire system minus the agent-name allowlist โ exactly the gap a third-party SDK needs to fill. Rivet's Sandbox Agent SDK does that; expect others if the API survives.
- macOS/Windows-only matters. The platform restriction makes this concretely a developer-laptop primitive, not a server-side one โ at least until Docker Desktop's Linux story changes. For production sandboxing on Linux today, the choices in microvm-2026 (Firecracker, Cloud Hypervisor, Kata) still hold.
Stability caveat
The API is undocumented and subject to change. Rivet's writeup acknowledges this directly โ it works today on Docker Desktop 4.58+, and that's the entire warranty. Any tooling built on this lives at the mercy of an internal-only surface that Docker has every right to break in the next minor release. This is the structural inverse of abi-stability (Win32 as the durable ABI on Linux) โ interesting to track as a counter-example of what happens when the upstream isn't committed to the contract.
See also
- microvm-2026 โ the broader microVM-for-agent-sandboxing survey (Docker Sandboxes mentioned at the platform level; this page is the API-level zoom-in)
- microvm โ architectural concept
- matryoshka-isolation โ containers-in-VMs sandwich pattern
- sandboxing-ai-agents โ four-layer taxonomy; the MITM proxy is Layer 3 baked in
- sandbox-agent-sdk โ Rivet's SDK on top of this API
- rivet-blog โ author entity
- crabtrap โ Brex's LLM-as-judge HTTP proxy; the same Layer-3 idea applied to traffic Docker's proxy isn't filtering on
- superhq, hazmat, bubblewrap-dev-env โ alternative substrate choices