Sandboxing AI Coding Agents Without Killing Developer Velocity
6 Apr 2026 · 8 min read
- AI Coding
- Security
- Dev Containers
- Operations
The hard part of AI coding is not getting a model to write code. The hard part is letting it run useful commands without quietly handing it your whole machine.
That tension shows up fast in real workflows. The agent wants to install packages, run tests, inspect the repository, build containers, and maybe hit an internal service. You want all of that to happen inside clear boundaries so a bad prompt, a confused tool call, or a risky dependency install does not spill across your laptop or production-adjacent environment.
The fix is not one magical sandbox. It is a layered setup: isolate execution, scope filesystem access, constrain network reach, and make sensitive actions require a different lane than routine coding work.
The threat model is boring, and that is why it matters
Most failures here are not movie-plot jailbreaks. They are ordinary engineering mistakes with better tooling behind them.
An AI coding agent can accidentally:
- modify files outside the intended repo
- leak secrets from shell history or local config files
- install packages with post-install scripts that touch the host
- run expensive or destructive commands because the task description was ambiguous
- persist credentials in places a later task can read
- open a network path to systems that were never part of the assignment
If the agent has broad host access, every one of those mistakes becomes more expensive.
Start with the right mental model
A container is not a complete security strategy. It is just one boundary.
For practical AI coding work, I like to think in four layers:
- Workspace scope — what files can the agent read or write?
- Runtime isolation — what process boundary contains the code execution?
- Network policy — what hosts can the agent reach?
- Approval path — what still requires a human or a separate trusted workflow?
If you only solve layer two, you still lose to sloppy mounts, broad credentials, or open egress.
A good default: dev container plus narrow mounts
For many teams, the best first step is not a heavyweight security platform. It is a repeatable development container with a very small blast radius.
The Development Containers spec is useful here because it standardizes the environment around the repository instead of around one engineer's laptop. The agent gets the same toolchain, package manager, and shell utilities every run. That reduces the temptation to give it extra host access “just so it works.”
What to mount:
- the target repository as writable
- a small cache directory if build performance matters
- nothing else unless there is a clear reason
What to keep out:
- your home directory
- SSH keys
- cloud credentials
- password manager sockets
- unrelated projects
- Docker socket access unless you explicitly need nested container builds
This is where teams get casual. They mount the repo, then add ~/.ssh, then .aws, then the host Docker socket, and suddenly the sandbox is decorative.
Read-only mounts are underrated
Docker's bind mount documentation makes the key point: bind mounts are writable by default, which means processes in the container can change the host filesystem unless you mark the mount readonly or ro.
That matters because AI agents do not need write access to everything they can read.
Useful pattern:
docker run --rm \
--mount type=bind,src=$PWD,dst=/workspace \
--mount type=bind,src=$HOME/.npm,dst=/home/dev/.npm,readonly \
--mount type=bind,src=$HOME/.gitconfig,dst=/home/dev/.gitconfig,readonly \
my-agent-image
Even better, avoid mounting global config at all unless the workflow breaks without it. If a mount exists only to make the environment feel familiar, it is probably too generous.
Treat network access as a separate permission
A lot of “sandboxing” discussions obsess over filesystem isolation and ignore egress.
But for coding agents, network access is often the real privilege:
npm installandpip installneed package registries- tests may call staging services
- build scripts may phone home
- helper tools may hit GitHub, Slack, or cloud APIs
Do not lump all of that together.
A practical split looks like this:
- No network for local editing, refactors, and static analysis
- Registry-only for dependency installation
- Allowlisted outbound for workflows that truly need GitHub APIs or internal test services
- Never ambient access to production endpoints from the same environment that executes untrusted code
If your platform cannot express this cleanly, use separate jobs or separate sandboxes for “edit/test locally” and “publish or deploy.”
MicroVMs are worth it when the agent gets more power
Regular containers are fine for a lot of local development work, but they still share the host kernel. That is why stronger isolation layers exist.
Firecracker is built around lightweight microVMs with a reduced device model and small attack surface. gVisor takes a different approach by putting an application kernel between the workload and the host kernel. Docker's new sandboxing model for AI agents also leans toward microVM-style isolation because it is a better fit once the agent needs to install tools, build images, or run less-trusted code paths.
You do not need microVMs for every toy script. You probably do want them when:
- the agent runs arbitrary repo code from many users
- the workload installs third-party dependencies often
- the sandbox is multi-tenant
- the host has credentials or data you really care about
- the agent can itself spawn containers or build artifacts
The pattern I like is simple: start with dev containers for reproducibility, graduate to microVM-backed sandboxes when the risk profile stops being “my own repo on my own machine.”
Never pass the host Docker socket casually
Mounting /var/run/docker.sock into a coding environment is one of the fastest ways to defeat your own isolation story.
Why? Because the workload can ask the host daemon to start privileged containers, mount arbitrary host paths, and effectively step around the restrictions of the original container.
If the agent needs container build capability, prefer one of these instead:
- a sandbox with its own nested Docker daemon
- rootless build tooling where practical
- a remote build service with scoped credentials
- a microVM environment that contains its own container runtime boundary
This is one of those places where convenience has a very clear security price tag.
Build two lanes: routine work and sensitive work
The cleanest operational design is not “one sandbox with every permission.” It is two lanes.
Lane 1: routine coding
Use for:
- reading and editing repo files
- linting
- unit tests
- formatting
- local type checks
- docs generation
Properties:
- no production credentials
- narrow filesystem mount
- no or limited egress
- short-lived environment
Lane 2: sensitive actions
Use for:
- creating releases
- deploying
- touching cloud infrastructure
- accessing private registries with write scope
- modifying secrets or environment config
Properties:
- separate workflow or separate executor
- explicit approval boundary
- audited credentials
- stronger logging and shorter credential lifetimes
This matters because the coding agent will eventually ask for something that is adjacent to deploy power. You want the system design, not the model's mood, to decide where that boundary sits.
Make the sandbox disposable
Persistent sandboxes drift. Temporary sandboxes fail louder, which is usually better.
A disposable environment gives you:
- fewer stale credentials left behind
- fewer “works on this container only” mysteries
- a cleaner audit trail per task
- easier rollback when package installs or scripts go sideways
Persist only what you need deliberately, such as package caches or artifact caches. Everything else should be cheap to rebuild.
A minimal policy that teams can actually maintain
You do not need a security dissertation to improve this setup. A short policy catches most of the real mistakes.
AI coding sandbox policy
- Mount only the target repo as writable.
- Mount caches read-only unless writes are required for performance.
- Do not mount the host home directory.
- Do not mount SSH agents, cloud config, or Docker socket by default.
- Default network mode is off; enable only the minimum required egress.
- Use a separate executor for deploys, releases, and infrastructure changes.
- Destroy the sandbox after each task unless a human explicitly keeps it.
That policy is boring, operational, and strong enough to change behavior.
What this looks like in practice
Here is a lightweight pattern for local or CI-backed agent runs:
{
"name": "repo-agent",
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"workspaceFolder": "/workspace",
"features": {
"ghcr.io/devcontainers/features/node:1": {
"version": "22"
}
},
"mounts": [
"source=${localWorkspaceFolder},target=/workspace,type=bind",
"source=${localEnv:HOME}/.npm,target=/home/vscode/.npm,type=bind,consistency=cached"
],
"postCreateCommand": "npm ci",
"remoteUser": "vscode"
}
Then tighten it before handing it to an agent:
- make extra mounts read-only where possible
- strip any credential-bearing files
- disable network unless setup truly requires it
- keep approvals outside the container for sensitive actions
The goal is not perfect purity. The goal is a setup where the default failure mode is annoying, not catastrophic.
Common mistakes
Mistake 1: confusing reproducibility with isolation
A dev container gives you a reproducible environment. That does not automatically mean a safe one.
Mistake 2: over-mounting for convenience
Every extra mount is a trust decision. Treat it like one.
Mistake 3: mixing package installation and deploy power
If the same environment can run untrusted install scripts and also deploy to production, you have built a very sharp foot-gun.
Mistake 4: keeping sandboxes alive forever
Long-lived sandboxes quietly accumulate state, credentials, and weird one-off fixes.
Final takeaway
Useful AI coding does not require giving the agent a blank check.
The winning pattern is layered: reproducible dev environment, narrow writable scope, read-only everything else, explicit egress rules, and a separate path for high-trust actions. Containers help. MicroVMs help more when the workloads get riskier. But the biggest improvement usually comes from saying “no” to ambient access that nobody can justify.
If your current setup mounts half your laptop into the agent so it can feel comfortable, that is not velocity. That is unsecured convenience dressed up as workflow.
References and resources
- Development Containers specification: https://containers.dev/
- Docker bind mounts documentation: https://docs.docker.com/engine/storage/bind-mounts/
- Docker Sandboxes overview: https://docs.docker.com/ai/sandboxes/
- gVisor documentation: https://gvisor.dev/docs/
- Firecracker microVM docs: https://firecracker-microvm.github.io/
Strong AI coding workflows start with narrow permissions, not good intentions.