Running a Coding Agent in an Isolated Environment

Run the agent in a container or virtual machine that holds only the repository and the tooling it needs, with credentials scoped narrowly and network egress restricted. That converts a successful prompt injection or a destructive command from a machine-level incident into a discarded environment.

What isolation actually buys

A coding agent runs commands. That is the point of it, and it is also the reason the machine it runs on is exposed in a way an ordinary editor is not.

Put it in a container or a virtual machine holding a checkout of one repository and the tooling that repository needs, and several things become true at once.

A destructive command affects a rebuildable thing. A recursive delete, a bad migration, a script that overwrites files: all of it lands inside a boundary you can discard and recreate in minutes.

A successful prompt injection has less to reach. The attack still succeeds in the sense that the agent follows the injected instruction. What changes is that the instruction executes somewhere with no access to your other projects, your personal files or your session tokens.

Dependency execution is contained. Installing and running unfamiliar packages is a normal part of the work and a well known delivery mechanism for hostile code. Doing it inside a disposable environment is straightforwardly safer than doing it on your laptop.

State drift stops mattering. Agents install things, change configuration and leave artifacts. A fresh environment per task means none of that accumulates.

What you are buying is a smaller blast radius, not immunity. The agent can still be manipulated; it simply has less to work with when it is.

What sits outside the boundary

This is where isolation is most often oversold, and the gaps matter more than the protection.

Credentials you put inside. An environment with a production database URL in it is isolated from your filesystem and connected to your production database. Isolation does not scope a credential; you do. Give the environment the narrowest token the task requires and prefer short-lived ones.

Network egress. By default a container can reach the internet, which is the exfiltration path for anything it can read and the download path for anything it wants to run. Restricting outbound traffic to what the work genuinely needs is a separate decision from isolating the filesystem, and it is the one more often skipped.

The repository itself. The code is inside the boundary because the agent has to work on it. So an agent that writes a subtle backdoor writes it into the thing you intend to keep. Isolation contains the environment and does nothing about the output.

Anything the agent pushes. A commit to a shared branch has left the boundary by definition.

Which leads to the point worth being clear about: isolation protects your machine, and review protects your codebase. Teams that adopt the first and relax the second have moved the risk rather than reduced it.

Speed is what determines adoption

An environment taking four minutes to become usable will be bypassed within a week, and a bypassed control protects nothing. Cache a base image with the toolchain and dependencies already installed so a fresh environment is seconds rather than minutes. This is the practical difference between a policy that holds and one that is quietly abandoned.

A setup that people actually keep using

One environment per task, discarded afterwards. Fresh state per task, nothing accumulating, and a compromised session ends when you throw it away.

A cached base image. Toolchain, language runtime and dependencies pre-installed. Rebuild it on a schedule rather than per run.

Mount one repository. Not a workspace directory containing several, and never a home directory.

Inject credentials narrowly and briefly. Environment variables passed at start rather than baked into the image, scoped to the single system the task needs, expiring quickly.

Restrict egress to a list. Package registries and the specific services the task requires. Default-deny is more work to set up once and it is what makes the boundary meaningful.

Keep review outside. Changes leave the environment as a branch and go through the same gates as any other contribution.

Log what the agent read and ran. After an incident the only question is what it touched, and that record has to exist beforehand.

One last reduction worth pairing with this. Isolation limits what an agent can reach; retrieval limits what it needs to. An agent pulling the specific passage a task requires ingests a fraction of the text one scanning a repository does, which shrinks both the attack surface and the bill. RDK's stacked retrieval is built for that, resolving most queries before the model sees anything at all.

Frequently asked questions

Should you run a coding agent in a container or VM?
For anything beyond trivial local experimentation, yes. It converts a destructive command or a successful prompt injection from a machine-level incident into a discarded environment. What it does not do is prevent the agent being manipulated, or stop bad code reaching your branch.
What does isolation not protect?
Credentials you place inside the environment, network egress unless you restrict it, the repository itself since the agent must work on it, and anything the agent pushes. Isolation protects your machine; review protects your codebase, and the two are not substitutes.
Why is restricting network access separate from isolation?
Because a container reaches the internet by default. That is the exfiltration path for anything the agent can read and the download path for anything it wants to run. Restricting outbound traffic to what the work needs is a distinct decision and the one more often skipped.
How do you stop people bypassing the isolated environment?
Make it fast. An environment taking four minutes to become usable gets bypassed within a week, and a bypassed control protects nothing. Cache a base image with the toolchain and dependencies already installed so a fresh environment starts in seconds.