---
title: "How to sandbox coding agents when a whole team runs them"
description: "To sandbox coding agents such as Claude Code and Codex, pick one of five isolation layers, keep credentials out of the sandbox and decide who owns approvals and machine time."
url: "https://aldena.ai/blog/sandbox-coding-agents"
---

# How to sandbox coding agents when a whole team runs them

Published 2026-11-11.

## A coding agent's shell can read whatever you can

To sandbox coding agents like Claude Code and Codex, start with the credentials, because each agent's shell runs with the permissions of whoever started it. On a laptop that means the SSH key in `~/.ssh`, the cloud profile in `~/.aws`, the `.env` file two directories up and the token your git credential helper stores.

A coding agent runs `npm install`, the test suite and whatever script the README suggests, and every one of those runs as you. [Dark Reading's report that AI coding agents leak thousands of secrets to GitHub](https://www.darkreading.com/cyber-risk/ai-coding-agents-leak-secrets-github) is the failure I plan around. A model that reads a key while debugging can paste it into a commit, a log line or a request to some API, and review on the diff never sees the request.

![Three panels: the agent's shell runs npm install, the test suite and the README's script as you, reads \~/.ssh, \~/.aws, a .env file and the git credential helper token, and can paste a key into a commit, a log line or an API request that diff review never sees](https://cdn.aldena.ai/images/blog/sandbox-coding-agents-1-20261112.png)

So the first thing I ask of any sandbox is which of those credentials the agent's shell can still read. Host files and the host kernel come second.

## Five isolation layers, and what each one shares with your machine

Coding agent sandboxes come in five layers, from an OS sandbox such as Seatbelt or bubblewrap to a separate remote machine, and each layer shares less with your laptop.

| Layer             | Example                                | Shares with your machine                    | An escape reaches                       |
| ----------------- | -------------------------------------- | ------------------------------------------- | --------------------------------------- |
| OS sandbox        | Seatbelt on macOS, bubblewrap on Linux | the kernel and every path the policy allows | your machine                            |
| Container         | Docker, a devcontainer                 | the kernel and every volume you mount       | the host                                |
| User-space kernel | gVisor                                 | a narrow set of system calls                | the gVisor layer before the host        |
| MicroVM           | Firecracker                            | a hypervisor                                | the hypervisor                          |
| Remote machine    | Boat or another cloud sandbox provider | nothing on your laptop                      | that machine and whatever it has stored |

Claude Code and the Codex CLI ship the first row built in. [Claude Code's sandbox](https://code.claude.com/docs/en/sandboxing) runs bash under Seatbelt on macOS and bubblewrap on Linux and WSL2. Codex keeps writes inside the active workspace, with [Seatbelt profiles on macOS and bubblewrap plus seccomp on Linux](https://learn.chatgpt.com/docs/permissions). I leave both on for every local run, since they cost nothing. They still sit on the machine that holds my keys, so I treat that row as protection against mistakes and look further down the table for anything a team shares.

gVisor answers the agent's system calls in a user-space kernel, while runc, the runtime under an ordinary container, hands them straight to the host kernel. A Firecracker microVM boots its own guest kernel behind a hypervisor. The remote row is the odd one out, because a provider runs one of those middle rows on its own hardware, far from everything on your laptop. For tool names in every row, there is a [community list of coding agent sandboxes](https://gist.github.com/wincent/2752d8d97727577050c043e4ff9e386e) dated May 2026.

![Five columns for OS sandbox, container, gVisor, Firecracker microVM and remote machine, each showing the boundary under the agent's commands, what it shares with your laptop and what an escape reaches](https://cdn.aldena.ai/images/blog/sandbox-coding-agents-2-20261112.png)

## A container is enough only when nothing secret is mounted into it

A Docker container shares the host's kernel and every volume you mount into it, so a coding agent inside can reach whatever that mount list exposes.

A devcontainer that mounts the home directory to keep git config working also mounts `~/.ssh` and `~/.aws`. A mounted `docker.sock` is worse, because it hands the agent the host's Docker daemon, which can start a privileged container with the host's root filesystem attached. When I wrote up [what it takes to self-host an always-on agent](https://aldena.ai/blog/self-hosted-ai-agent), Docker on my own machine was the step I trusted least, and the mounts are why.

I check a setup against [Northflank's list for a secure coding agent sandbox](https://northflank.com/blog/how-to-run-ai-coding-agents-in-a-secure-sandbox), which has five items: kernel-level isolation, short-lived sessions, default-deny egress, scoped credential injection and audit logging. A plain `docker run --rm` on a laptop gives you the short-lived session and none of the other four.

![A Docker container whose home directory mount also exposes \~/.ssh and \~/.aws and whose docker.sock mount reaches the host's Docker daemon, beside Northflank's five checks where docker run --rm meets only short-lived sessions](https://cdn.aldena.ai/images/blog/sandbox-coding-agents-3-20261112.png)

## Keep credentials out of the sandbox and put the network on an allow list

[LangChain's sandbox docs](https://docs.langchain.com/oss/python/deepagents/sandboxes) say a sandbox stops neither context injection nor network exfiltration, so every credential an agent can read is one it can send somewhere.

Inside the sandbox, I keep long-lived secrets out of the agent's session altogether. OpenAI's legacy Codex cloud ran tasks in [isolated containers that held secrets only during setup](https://learn.chatgpt.com/docs/agent-approvals-security), before the agent started, and I copy that pattern for package-registry tokens. A key the agent needs while it works, such as a test account's API key, should be scoped to that one job and cheap to rotate. The agent's own login counts as well, since an `auth.json` or a session token on the sandbox's disk is readable by every command the agent runs.

Where the sandbox can connect decides whether a leaked secret leaves. Codex starts with no network access. Claude Code sends traffic through a proxy that runs on the host, outside the sandbox, and checks each hostname against allowed and denied domains, so a compromised shell can't edit its own allow list. For a team, I want that list to name the registries and APIs the build needs and nothing else, and I want a person to own it.

![Secrets present only during setup, then the agent's shell sending traffic through a proxy on the host that allows the registries and APIs the build needs and denies anything not on the list](https://cdn.aldena.ai/images/blog/sandbox-coding-agents-4-20261112.png)

## Sandbox the agent, not just the code it writes

Claude Code and Codex run shell commands from inside their own harness, so sandboxing only the generated code leaves the process that types every command outside the sandbox.

A [thread on r/LocalLLaMA](https://www.reddit.com/r/LocalLLaMA/comments/1u3eu0a/instead_of_sandboxing_the_ai_agent_sandbox_only/) argues for putting only the code the agent runs in the sandbox. Matthew Casperson at Octopus makes a related case, that [shared, task-specific agents should have their tools constrained](https://octopus.com/blog/ai-agent-sandboxes) through ordinary auth, rate limits and observability.

Both arguments hold for agents you build yourself. When the harness is your code and every tool is a function you wrote, LangChain calls the pattern a sandbox used as a tool, and the agent loop can stay outside with nothing dangerous in reach.

An off-the-shelf coding agent has no clean split. Claude Code and Codex hold the API credentials, read and edit files with their own tools, and spawn the shell that runs `npm test`, all on one machine. The built-in sandboxes fence the commands, while the harness keeps its credentials and its file tools on the host. To get both inside, I run the whole agent on a machine that holds nothing else.

![Three setups compared: a self-built agent with only its code in the sandbox, Claude Code or Codex with only the shell fenced while credentials and file tools stay on the host, and the whole agent on a machine that holds nothing else](https://cdn.aldena.ai/images/blog/sandbox-coding-agents-5-20261112.png)

## A team has four questions a solo setup never asks

A team that sandboxes coding agents has to settle four questions a solo developer never meets, and the hardest is who owns the sandbox once its builder leaves.

- **Who owns the sandbox.** On a laptop the developer owns it, and when that developer leaves, the setup leaves too. A shared sandbox needs one owner who holds the provider account, picks the machine size and decides what the setup script installs.
- **How many agents share a checkout.** I allow one writer per checkout. Two agents editing the same checkout at once produce conflicts neither caused alone, so [parallel work goes in separate checkouts](https://aldena.ai/blog/run-multiple-claude-code-agents), the rule I laid out in the [coding agents guide](https://aldena.ai/blog/ai-coding-agents-guide).
- **Where approvals go.** An approval prompt in one developer's terminal works while that developer is watching. On a team the question has to land where any member can answer it, or [an unattended agent's run](https://aldena.ai/blog/autonomous-coding-agent) waits for its owner to wake up.
- **Who pays.** A sandbox that never sleeps bills all night. I want machine time on the team's own provider account and model usage on the team's keys or each member's plan, so every line of the bill has one owner.

## How sandboxing coding agents works in Aldena

Aldena runs Claude Code and Codex inside each conversation's own sandbox, on a sandbox provider such as Boat that an owner or admin connects once with an API key.

![The team Providers page with the Boat sandbox provider not connected and a field to paste a Boat API key](https://cdn.aldena.ai/images/blog/sandbox-coding-agents-6-20261112.png)

I built the isolation around the project. An owner or admin picks the provider and a machine size when creating a project, and two [projects never share a filesystem](https://aldena.ai/features/isolated-projects). Agents in one project have no tool that reads another project's sandboxes, secrets or history. Environment variables and connector credentials are set per project, and only that project's agents can use them, so a leaked key is one project's key. The setup script runs once on each new sandbox with sudo. The agents run without sudo or Docker.

Inside a project, the Delivery agent works one report at a time down the [org chart](https://aldena.ai/features/org-chart), so two agents never edit the same checkout at once. Nobody on the team has to enforce one writer per checkout by hand. The same repository can also be connected in two projects, where each clones it into its own conversations' sandboxes and opens its own pull requests.

Each conversation's sandbox starts with its first turn, sleeps 30 minutes after its last command and keeps its files until the conversation's next turn wakes it. The sandbox provider bills that machine time to the team's own account, per second on Boat. For the [agents](https://aldena.ai/features/agents) themselves, Claude Code runs on each member's own Claude plan or the team's Anthropic key, and Codex runs on the team's OpenAI key, because ChatGPT plans aren't supported yet. Usage on a team key goes straight to the team's account with that provider. Aldena adds nothing on top of either bill.

Approvals land where the whole team can see them. Every tool an agent can call carries an allow, ask or deny policy, set per project. When a call falls under ask, the run pauses and the approval waits in one team [Inbox](https://aldena.ai/features/human-in-the-loop), where any member can answer it for seven days. The work itself ends in a pull request, which the Delivery agent opens against the default branch before it stops. No agent merges its own work.

![An Inbox card where Project Setup waits on three add_project_memory approvals with allow once, always allow and deny buttons](https://cdn.aldena.ai/images/features/human-in-the-loop/inbox-batch-20261108.png)
