Blog / 31 October 2026
Deep dive · 31 October 2026 · 8 min read
Is a devcontainer enough for AI coding agents?
A devcontainer is a reasonable boundary for a coding agent working on a repository you trust, and a weak one for a repository you do not: the agent's commands stay off your host, but its credentials sit inside the container with it. The question that decides between a devcontainer, Docker Sandboxes and a local microVM is where the keys live.
01What does a devcontainer isolate for an AI coding agent?
A development container is a Docker container described by a devcontainer.json file in the repository. An editor that supports the spec, such as VS Code, a JetBrains IDE, Cursor or GitHub Codespaces, connects to it, and the terminal, language servers and build tools run inside. Anthropic's Claude Code documentation puts the benefit plainly: commands Claude runs execute inside the container rather than on the host, while edits to project files appear in your local repository, because the project folder is bind-mounted in.
That is a real improvement over running an agent directly on a laptop. A stray rm -rf hits the container's file system, not your home folder, and the toolchain is the same for every engineer. But a container is a set of namespaces and control groups on a shared kernel, not a separate machine, and the bind-mounted workspace is your real working copy. Anything the agent deletes or rewrites there is deleted or rewritten on the host too.
Anthropic is direct about the limit. Its devcontainer page warns that when Claude Code runs with --dangerously-skip-permissions, a dev container does not prevent a malicious project from exfiltrating anything accessible inside the container, including the Claude Code credentials stored in ~/.claude. It recommends dev containers only for trusted repositories, and says to avoid mounting host secrets such as ~/.ssh or cloud credential files.
02Where do credentials live inside a devcontainer?
Usually in several places at once. Claude Code keeps its authentication token under ~/.claude, and Anthropic's guide shows how to persist that folder across rebuilds with a named volume. Cloud provider credentials are passed in as environment variables through containerEnv or a Codespaces secret, which Codespaces exposes as environment variables inside the container. Each of those is readable by every process the agent starts, including packages it installs and scripts a prompt injection talks it into running.
The editor adds more. Microsoft's Dev Containers documentation says the extension reuses your local Git credential helper, so credentials entered locally work in the container and the other way round; it forwards your local SSH agent when one is running; and it copies your .gitconfig in on startup. That is convenient for a developer and means a hijacked agent inside the container can push with your Git identity or sign in over SSH with your keys, without ever reading a key file.
~/.claude: the agent's own sign-in token.containerEnvand Codespaces secrets: API keys and cloud credentials as environment variables.- Git credential helper and SSH agent forwarding: your Git and SSH identity, usable from inside.
- Anything else mounted in: Anthropic's advice is to prefer repository-scoped or short-lived tokens.
03What does the devcontainer firewall block, and what does it leave open?
Anthropic's reference container ships an init-firewall.sh script, and it needs the NET_ADMIN and NET_RAW capabilities to run. As published, it sets the default output policy to drop, builds an ipset from GitHub's published address ranges plus the addresses that registry.npmjs.org, api.anthropic.com, sentry.io, statsig.com and the VS Code marketplace hosts resolve to when the script runs, and rejects everything else. It then checks that example.com is unreachable and api.github.com is reachable.
Reading the script also shows what stays open, which is worth knowing before you rely on it. It allows outbound DNS on UDP port 53 and outbound SSH on TCP port 22 to any destination, and it accepts traffic to and from the host's /24 network. DNS to any server is a known exfiltration channel, and every GitHub address range is reachable, which includes services that accept uploads. Addresses are resolved once at start, so a provider that changes addresses later is refused, while a shared address admits every site served from it. The rules live in the container's own iptables, so they hold for as long as the agent cannot become root inside it.
One more structural point: the repository writes the boundary. Under the Dev Container spec, initializeCommand runs on the host machine, and runArgs, mounts, capAdd and privileged all come from the repository's devcontainer.json. Anthropic notes the same about policy files copied in by a Dockerfile: anyone with write access to the repository can change or remove that step. For your own trusted code that is fine. For an untrusted clone, opening its devcontainer means running its configuration.
04How are Docker Sandboxes different from a devcontainer?
Docker Sandboxes, driven by the sbx CLI, take a different shape. Docker's security documentation says each sandbox runs in a microVM with a separate kernel and no shared memory or processes with the host, and has its own Docker Engine with no path to the host daemon. Outbound TCP is governed by a deny-by-default policy and goes through a proxy on the host; UDP is blocked unless an experimental setting is turned on, and ICMP is blocked.
The biggest difference for coding agents is credentials. Docker documents that a host-side proxy injects API keys into HTTP headers and that the raw credential values never enter the VM: the agent sends a sentinel value, and the proxy swaps in the real key after the request has left. Docker also flags a limit of its own: the default allowed domains include broad wildcards such as *.googleapis.com, and sbx policy ls shows what is allowed. The workspace is mounted through a file-system passthrough at the same path as on the host, so changes are instant in both directions, as with a devcontainer.
05Devcontainer vs VM: which questions decide it?
None of these is the wrong tool. A devcontainer is a good fit for team consistency on trusted code, especially with prompts left on. A microVM with a host-side credential proxy fits when the repository, its issues or its dependencies are not yours, or when the agent runs unattended. A full VM in UTM or Lima is another option when you want a whole separate machine and are happy to manage it.
The labels matter less than the answers to four questions, and they are worth asking of any setup, including one you already run.
- Where do the keys live? Inside the boundary, they are readable by whatever runs there. Outside it, they can only be spent through the proxy.
- Who writes the boundary? A
devcontainer.jsonin the repository, or a configuration you keep yourself. - What is the way out? Check DNS, SSH and broad allowed domains, not only HTTPS.
- What does undo look like? A bind-mounted workspace changes the real folder; plan for Git or snapshots.
Takeaways
- A devcontainer moves an agent's commands off the host, but the bind-mounted workspace is still your real folder.
- Anthropic warns that with
--dangerously-skip-permissions, a dev container does not stop a malicious project exfiltrating what is inside it, including~/.claudecredentials. - VS Code's Dev Containers extension shares your Git credential helper and SSH agent with the container by default.
- The reference
init-firewall.shdrops most traffic but allows DNS and SSH to any destination and all GitHub ranges. - Docker Sandboxes use microVMs and a host-side proxy, so raw keys never enter the VM; review its default allowed domains.
- Decide by where the keys live and who writes the boundary, not by the word container or VM.
Where kosa8 fits
kosa8 sits on the microVM side of this comparison and runs on your own Apple silicon Mac or x86-64 Linux machine. kosa8 agent run starts a built-in kit such as claude, codex, gemini or opencode in its own microVM with its own kernel; the machine sees one workspace folder and nothing else on the host. For those brokered kits the API key stays on your computer: an egress broker adds it on the way out and the sandbox holds only a placeholder, so there are 0 real keys inside. The network is closed except through the broker, and DNS questions are answered on the host, with unlisted names refused. The boundary is a kit file you write or a built-in, not the repository's configuration, and --dry-run prints it before anything starts. The kosa8 docs list the limits: the copilot kit still passes its token into the sandbox, and an agent can still spend a brokered key through the routes it is allowed.
Check yourself · +100 XP
Claude Code runs with --dangerously-skip-permissions in a devcontainer opened on a malicious repository. According to Anthropic's documentation, what can the project still do?
Anthropic's devcontainer page says the container does not prevent a malicious project from exfiltrating anything accessible inside it, including ~/.claude. That is why it recommends devcontainers for trusted repositories only, and why keeping keys outside the boundary matters.
Questions people ask
Is a devcontainer safe enough for Claude Code?
For a repository you trust, a devcontainer with a non-root user and an egress firewall is a reasonable setup. For an untrusted repository, Anthropic warns that a malicious project can exfiltrate anything inside the container, including Claude Code's credentials, so use a boundary that keeps keys outside.
Does the devcontainer firewall stop data exfiltration?
It narrows it. The reference init-firewall.sh drops most outbound traffic but allows DNS on UDP 53 and SSH on TCP 22 to any destination, plus all of GitHub's address ranges. Any allowed destination that accepts data is still a way out.
What is the difference between a devcontainer and Docker Sandboxes?
A devcontainer is a container on a shared kernel with credentials usually inside it. Docker documents its Sandboxes as microVMs with a separate kernel, a deny-by-default host proxy for outbound TCP, and credentials injected by that proxy so raw values never enter the VM.
Sources
- Development containers — Claude Code docs
- init-firewall.sh (reference dev container) — anthropics/claude-code on GitHub
- Dev Container metadata reference — Development Containers specification
- Sharing Git credentials with your container — VS Code docs
- Docker Sandboxes: security — Docker docs
- Docker Sandboxes: architecture — Docker docs
- Docker containers vs microVMs: which isolates an AI agent better? — kosa8 guides
- How do I give an AI agent API keys without exposing them? — kosa8 guides
- How do I run Claude Code safely on a Mac? — kosa8 guides
Written by the kosa8 team. Every kosa8 command was checked against the CLI, and every claim about another product links to that product's own documentation. Spotted a mistake? Tell us.
Try it on your own machine
Give your next agent its own sealed machine.
One line installs kosa8 on your own machine. Every feature, plans from $29 a month.