Your Agent's Permissions Belong in an OCI Image
Docker spent September making an argument most of us have been avoiding: the hard part of running coding agents unattended is not isolation. It is authority. On September 24 the company shipped Cloud Sandboxes, a pay-as-you-go host for the microVM sandboxes it launched earlier this year, and open-sourced the Sandbox Kit Specification v3 under Apache 2.0. It says an agent's permissions should be declared in a versioned artifact, reviewed like code, and enforced by any conforming runtime, a DevOps idea that arrived for agents before it arrived for services.
Why a container is the wrong boundary
Docker's framing starts with a useful distinction. A container packages an application: one fixed workload, namespaces and cgroups, and a boundary that is the host kernel. An agent is a probabilistic actor. It decides what to do next, and it does that to your filesystem, your credentials, and your cloud account. It will install a package that needs root and open a port nobody planned for. The container's boundary is the same kernel the actor is probing, which makes it a weird place to park something that improvises.
Docker Sandboxes put the agent in a microVM with its own kernel, so the boundary sits below anything the model can reach. Fine. But an empty microVM is not an environment. Something still has to say which agent runs there, which tools and MCP servers it gets, and exactly what it may touch. That was the missing half, and it has always lived in shell history, CI variables, and someone's memory.
A Kit is an OCI image that carries its own permission slip
The v3 spec makes that half first-class. A Kit is an ordinary OCI image. The declarations ride in one manifest annotation, vnd.docker.sandbox.kit.descriptor, and the layers carry the content. No custom media type, no sidecar file. You build a Kit with docker buildx build, pull it with docker pull, scan it with the tools you already run, sign it, and use it in a FROM. Pin the digest and you pin content, declarations, and metadata together, so what staging runs is provably what production runs.
The spec ships two kinds. A workload supplies the root filesystem and runs. A mixin is an overlay: a CLI with its network rule, or a credential binding. You launch one workload plus any mixins. Here is the GitHub CLI mixin from the repository, and it reads like nothing else in the container ecosystem:
capabilities:
- type: com.docker.sandbox/network-policy@2
config:
runtime:
allow:
- github.com
- hosts: [api.github.com]
methods: [GET, HEAD, POST, PATCH, PUT, DELETE]
deny:
- hosts: [api.github.com]
methods: [DELETE]
paths: [/repos/**]
- type: com.docker.sandbox/credential@1
optional: true
config:
service: github
apiKey:
name: GH_TOKEN
proxyManaged: true
inject:
- {domain: api.github.com, header: Authorization,
format: "Bearer %s"}
Two things deserve a second read. First, deny wins: the token that can open a pull request cannot delete the repository, because the policy carves DELETE under /repos/** out of an otherwise generous allow. Second, the credential is proxy-managed. A conforming runtime injects the real token into requests aimed at the named domains, and inside the sandbox there is only a sentinel value. A prompt injection cannot exfiltrate a secret the agent never held. September's cautionary tale fits here: an agent provisioned five 20-gigabit EC2 instances scanning the DN42 hobby network and left its operator a $6,531 AWS bill. It had credentials and nothing between them and the API.
Asks, conforming runtimes, and refusing to launch
The grammar is deliberately humble. A Kit grants itself nothing; every entry is a request, and the host decides. A conforming runtime blocks hosts not on the list, and a required request the host cannot satisfy refuses the launch instead of starting the agent with less authority than it declared. Without a conforming runtime the annotation is inert, just an image. Docker Sandboxes is the first implementation that enforces the pages, with conformance suites for both artifacts and runtimes. Capability types version independently, and mixins compose through a dependency graph of provides and requires. The resolver is strict on purpose: exactly one workload, no silent shadowing when two Kits provide the same name, network rules union, incompatible requests are an error rather than a coin flip.
The diff is the review, and one gate does not need a reader
Here is why this matters to anyone who runs a pipeline. When the next version of a Kit asks for another host or a second credential, that is a change in authority, not a software update, and it shows up in a pull request as added lines a human can refuse. Review depends on somebody reading, so the spec defines a second gate that does not. Every descriptor reduces to a normalized set of everything the host would have to grant. A gating runtime records that set; a new version inside what was already granted applies silently, and any widening stops and asks. Removing a deny rule counts as widening. If a future GitHub Kit quietly drops the DELETE carve-out, the upgrade holds at the gate. Try doing that with a docker run flag or an IAM role someone pasted into a CI variable in 2023.
The cloud half, and why the spec is not a feature
Cloud Sandboxes runs the same Kits with the same trust model on Docker-managed compute. The CLI is identical, boot lands in the low hundreds of milliseconds, and sbx move my-project --to cloud captures the filesystem and recreates it on the other side. Pricing is compute-metered by the second, from $0.07 an hour for a 1 vCPU micro to $1.12 for a 16 vCPU box, with paused sandboxes free and a 24-hour session ceiling.
The strategic bet: Docker donates the spec to the CNCF, because a format for deciding what an agent may do is worth less if it belongs to whoever sells the runtime. I want to believe that, and its value depends entirely on a second runtime showing up. Docker is not alone: GKE, DigitalOcean, and Cloudflare all shipped agent runtimes this year, and InfoQ's 2026 trends report calls the field an infrastructure arms race. Docker's move is the one that standardizes the permission layer instead of just selling more isolation.
Not only agents
The last section of the spec is the sleeper. Agents forced the problem open because the authority they ask for is so large, but ordinary services arrive with unwritten expectations too: the endpoints they call, the credentials they need, the volume that must survive a restart. That knowledge lives in a Helm chart, a runbook, or a colleague who is about to leave. Kits are where any software writes down what it needs from the world around it.
If you run coding agents against real repositories, the secret-proxy and deny-wins ideas pay off today. If you are a platform team, the transferable lesson does not require Docker at all: declare the environment your workloads need as a reviewable artifact, gate widenings automatically, and refuse to launch when the host cannot satisfy the declared grants. The Dockerfile made software reproducible. Something still has to make authority reproducible, and for the first time there is a spec-shaped candidate.
Comments