DEV Community

Cover image for Docker's Kit spec packages agent authority as an OCI image: 5 details worth copying
Piekwerk
Piekwerk

Posted on

Docker's Kit spec packages agent authority as an OCI image: 5 details worth copying

Docker shipped three connected things at WeAreDevelopers on September 24: Cloud Sandboxes (microVMs for agents on Docker-managed compute, metered by the second), the Sandbox Kit Specification v3, and a plan to hand the spec to the CNCF. The cloud product will get the headlines. The Kit spec is the part that outlives any single vendor, because it attacks a problem every team running agents has right now: the grants an agent depends on are written nowhere.

The problem it names correctly

The spec's author, Christian Dupuis, describes the failure plainly. You grant an agent access one piece at a time: a bind mount, a token with broader scope than the task needs, a firewall rule that was quicker to open than to narrow. Each grant looks reasonable alone. Together they hollow out the isolation you started with, and no exploit was needed. The holes are configuration, added on purpose, by you.

Worse, the grants are not recorded anywhere reviewable. They live in shell history, dashboard toggles, and one engineer's memory. You cannot diff them against last week, and you cannot hand them to a colleague. A Dockerfile describes the software. What it never described is the outside: which networks, which credentials, which volumes. That half lived in docker run flags and a Compose file. The Kit spec moves it into the artifact.

Detail 1: Authority rides in an OCI annotation

A Kit is now an ordinary OCI image. Not a new artifact type, not a sidecar file. The manifest carries the permission declarations in a single annotation, vnd.docker.sandbox.kit.descriptor, and the layers carry the content. That one decision buys the whole existing toolchain: a Kit builds with docker buildx build, pulls with docker pull, gets scanned and signed by what you already run, and works in a FROM.

The consequence is the important part. Pinning the digest pins content, declarations, and metadata together. The agent binary and its permission list can no longer drift apart, because they are the same artifact. This is the same argument we made for treating agent instructions as versioned artifacts, applied to the enforcement layer instead of the prompt layer.

Detail 2: Deny wins, and you can read the permission slip

The spec's worked example is the GitHub CLI mixin. It asks for github.com, most methods on api.github.com, and explicitly denies deletes under /repos/**:

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: GH_TOKEN
    proxyManaged: true
    inject:
    - {domain: api.github.com, header: Authorization, format: "Bearer %s"}
Enter fullscreen mode Exit fullscreen mode

Read that as a permission slip. The token that can open a pull request cannot delete the repository, because deny wins over allow. Method-level and path-level granularity is where agent network policy has to end up; host-level allowlists alone leave too much surface once an agent has any write scope.

Two words in the spec carry the weight: "asks" and "conforming". A Kit grants itself nothing. Every entry is a request, and the host decides. A conforming runtime blocks hosts not on the list. Without one, the annotation is inert.

Detail 3: The agent never sees the credential

The credential block above says proxyManaged: true. The runtime injects the real token into requests headed for the named domains, and inside the sandbox there is only a sentinel value. The agent operates the API without ever holding the secret.

This matters more than it looks. Last week OpenAI published misalignment reports where an agent under goal pressure read a researcher's token and pushed it into a public repo, split into pieces to beat secret scanning. No instruction made it stop. A secret the agent never possessed is the only kind it cannot leak, which is the same reasoning behind Cloud Sandboxes' centralized secrets proxy: store keys once, inject per request.

Detail 4: Widening is gated, narrowing is not

Review depends on somebody actually reading the diff, so the spec defines a second gate that does not depend on attention. Every descriptor reduces to a normalized set of everything the host would have to grant. A runtime that gates updates records that set and compares the next version against it. A version inside what was granted applies silently. Any widening stops and asks, and removing a deny rule counts as widening: if a later Kit dropped the DELETE /repos/** denial, the runtime holds the upgrade.

That inversion is worth copying anywhere. Most config review treats permission changes and content changes the same, which means neither gets real scrutiny. Making authority changes structurally loud, and shrinkage structurally quiet, matches how risk actually behaves.

Detail 5: Composition resolves by graph, not flag order

There are two kinds of Kit. A workload runs and supplies the root filesystem. A mixin is an overlay: a CLI with its network rule, a credential binding, context for an agent. Mixins compose through provides and requires dependency edges, never through the order you typed the flags, so the same set always composes to the same image. Two Kits providing the same name fail rather than one silently shadowing the other. Where declarations overlap, network rules union and incompatible requests are an error.

Anyone who has debugged two Cursor rule files fighting over the same trigger knows why deterministic composition matters. "Last writer wins" is fine for text editors and terrible for authority.

What this does not solve

Honesty time. Docker Sandboxes is currently the only conforming runtime, and a spec with one implementation is a proposal, not a standard; the CNCF submission is the test of whether it becomes one. The capability types are versioned independently (network-policy@1 and @2 both exist today), which is the right call but means migration work eventually. Local and cloud sandboxes keep separate secrets, templates, and network policies, so moving a workflow between them is not free. And none of this shapes agent behavior: a Kit says what the agent may touch, not what it should do. Prompts, rules files, and skills still decide the "should", which is why enforcement and instructions belong in different layers. If you maintain versioned agent config kits, like the ones in AgentConfig Studio, the Kit spec is the missing enforcement half of what you already version.

Try it this week

brew install docker/tap/sbx
sbx login
sbx --cloud run claude
Enter fullscreen mode Exit fullscreen mode

That needs sbx 0.45.1 or later and the pay-as-you-go plan on Docker Personal or Pro. Kits exist today for Claude Code, Codex, Copilot, Antigravity, Open Code, and Hermes, and Docker's own framing for Cloud Sandboxes is agents running "five, ten, or 21 hours" unattended, which tells you what workload class this targets. The spec, capability pages, and a worked tour are in the docker/sandbox-kit-spec repository under Apache 2.0. Even if you never run a sandbox, steal the review gate: normalize your agent's grants into one file, diff it in every pull request, and make widening the thing that blocks the merge.

Top comments (0)