Background: The Risk of Coding Agents Isn’t “They Can Write Code,” It’s “They Can Execute Actions”
The biggest difference between a coding agent and a standard code completion tool is that the agent doesn’t just generate text. It reads project files, modifies code, runs tests, installs dependencies, invokes command-line tools, and even connects to external services. Once an agent gains shell, filesystem, and network capabilities, it enters a risk model much closer to an “automated ops script.”
In this model, the problem isn’t just whether the model is smart. It’s about what it is allowed to see, modify, access, and when it must stop and ask for confirmation. A miswritten prompt, an anomalous dependency script, a test command with side effects, or a third-party package executing a script during installation can all cause the agent to perform unexpected operations.
Therefore, a production-grade coding agent should not rely solely on “trusting the model not to misbehave.” A more robust design places the agent inside an auditable, rollback-capable, and restrictable sandbox runtime, decoupling model capabilities from system permissions.
Core Principle: Split Agent Execution into a Control Plane and an Execution Plane
A practical coding agent sandbox can typically be broken into two parts:
The Control Plane handles model invocation, task state, tool routing, permission policies, approval workflows, audit logs, and recovery logic. It decides whether the agent can proceed and records every step.
The Execution Plane is responsible for actually running commands, reading/writing files, installing dependencies, starting local services, exposing preview ports, and saving snapshots. It should be replaceable—it could be a local Unix sandbox, a Docker container, a cloud container, a temporary VM, or a managed sandbox provider.
The OpenAI Agents SDK documentation on sandbox agents describes this boundary as a separation of harness and compute: the harness is the model and tool control layer, while the compute is the sandbox execution layer for reading/writing files, running commands, installing dependencies, exposing ports, and snapshotting state. The value of this separation is that authentication, billing, auditing, and human review can remain on the trusted control plane, while the execution environment only receives the narrow permissions needed for the task.
File Boundaries: Default to Workspace Writes Only, Explicitly Deny Sensitive Files
Filesystem permissions are the first line of defense for a coding agent sandbox. A practical default policy looks like this:
| Level | Policy | Example |
|---|---|---|
| 1 | Allow read access to minimal system paths needed for tools | /usr/bin, /lib |
| 2 | Allow read/write access to code files in the current workspace | :workspace_roots set to writable |
| 3 | Set control directories to read-only or stricter | .git, .devcontainer, .codex |
| 4 | Explicitly deny reading sensitive files | **/*.env, **/*secret*, **/*credential* |
| 5 | Prevent access to sibling repos or user home directories via ../ | Path traversal denial rules |
An example from the OpenAI Codex permissions documentation illustrates this pattern: workspace roots can be set to writable, while more specific rules deny **/*.env. The documentation also notes that more specific deny rules override broader read/write authorizations.
A simplified permission configuration can be expressed like this:
default_permissions = "project-edit"
[permissions.project-edit]
description = "Project editing with narrow filesystem and network access."
extends = ":workspace"
[permissions.project-edit.filesystem]
":minimal" = "read"
[permissions.project-edit.filesystem.":workspace_roots"]
"." = "write"
".devcontainer" = "read"
".git" = "read"
"**/*.env" = "deny"
"**/*secret*" = "deny"
"**/*credential*" = "deny"
[permissions.project-edit.network]
enabled = true
[permissions.project-edit.network.domains]
"api.openai.com" = "allow"
"objects.githubusercontent.com" = "allow"
"*.github.com" = "allow"
"tracking.example.com" = "deny"
The key point here isn’t the configuration syntax itself, but the permission modeling approach: start with the minimal runnable boundary, then use deny rules to carve out sensitive areas. Don’t open up the entire home directory and then rely on a prompt asking the agent “not to look at sensitive files.”
Network Allowlists: Decompose “Internet Access” into an Explainable Domain Policy
Many coding agent tasks require network access: installing dependencies, reading package indexes, accessing GitHub, calling model APIs, fetching test fixtures. But “needs network” doesn’t equal “needs access to any address.”
A safer approach is to decompose network permissions into three layers:
Layer 1: No Network by Default
Local refactoring, static analysis, and unit tests should execute in a network-free environment first. The output quality of these tasks should not depend on network access.
Layer 2: Task-Level Allowlist
When a task genuinely needs network access, only allowlist specific domains, for example:
- Code Hosting:
github.com,gitlab.com,*.github.com - Package Manager Mirrors:
registry.npmjs.org,pypi.org,crates.io - Model APIs:
api.openai.com,api.anthropic.com - Internal Services:
artifacts.internal.example.com
Layer 3: Explicit Approval for Local and Internal Network
The following addresses must be treated as high-risk actions:
localhost,127.0.0.1,::1- Private network ranges (
10.0.0.0/8,172.16.0.0/12,192.168.0.0/16) - Unix sockets (e.g.,
/var/run/docker.sock) - Cloud metadata addresses (e.g.,
169.254.169.254) - Kubernetes API Server, database ports, etc.
Special Note: For coding agents,
/var/run/docker.sock, local database sockets, Kubernetes kubeconfig, and cloud CLI credentials are often more dangerous than public internet access—they are local escape hatches.
Approval Flows: Must Stop at Sandbox Boundaries
The sandbox isn’t about preventing the agent from ever doing complex tasks; it’s about making risky actions explicit. Normal code editing, running tests, and formatting files can happen automatically. Cross-boundary actions must enter an approval flow.
Approval Trigger Conditions
| Category | Trigger Condition |
|---|---|
| Sensitive Files | Reading or modifying .env, secrets, certificates, cloud credentials |
| Path Escalation | Writing to paths outside the workspace |
| Bulk Operations | Deleting many files or executing irreversible commands |
| Network Escalation | Accessing network domains not on the allowlist |
| High-Risk Tools | Using Docker socket, SSH, cloud CLI, database clients |
| Configuration Changes | Modifying CI/CD, deployment scripts, permission configs, or supply chain configs |
The OpenAI Codex sandboxing documentation distinguishes between sandbox and approvals as two cooperating controls: the sandbox defines technical boundaries, and the approval policy decides when to stop and ask. This distinction is well-suited for direct implementation in engineering design: the sandbox handles “hard limits,” and approvals handle “cross-boundary decisions.”
Containers Are Not a Silver Bullet: Agent Sandboxes Also Need Auditability and Recoverability
Many teams treat “putting it in Docker” as the entirety of sandboxing. But a container is just one implementation of the execution plane and doesn’t automatically solve all problems.
Containers can isolate processes, filesystem views, and dependency environments, but you still need to configure user permissions, mount paths, capability sets, seccomp, network policies, resource limits, and credential injection methods. The BPFContain paper points out that while Linux containers use namespaces and resource partitioning, the isolation semantics rely on a patchwork of mechanisms, making policies difficult to understand and audit. This is especially critical for coding agents, as they dynamically generate commands, making their behavioral boundaries far less predictable than standard web services.
Therefore, a coding agent’s sandbox runtime should provide at least three additional capabilities:
1. Snapshots and Rollbacks
Save the workspace state before each task begins. After the agent executes, generate a diff. The user confirms before merging. On failure, revert to the pre-task state.
2. Complete Audit Logs
Include model requests, tool calls, shell commands, exit codes, file diffs, network access, approval records, and final results. Audit logs should not be stored only within the sandbox; they should be synced to the control plane to ensure traceability even after the sandbox is destroyed.
3. Resource Limits
Limit CPU, memory, disk, process count, execution time, and output size to prevent erroneous commands or malicious scripts from making the development machine or shared runner unavailable.
Engineering Implementation: A Viable Production Pipeline
A robust coding agent execution pipeline can be designed in the following order.
Step 1: Declare Scope Before Task Entry
When a user submits a task, the system first identifies the task scope:
- Target repository and allowed modification directories
- Whether dependency installation is allowed
- Whether network access is allowed
- Whether running tests is allowed
- Whether modifying configuration or deployment files is allowed
For high-risk tasks (e.g., “fix CI and push,” “adjust Terraform,” “clean up historical files,” “upgrade all dependencies”), default to a stricter profile rather than reusing standard code editing permissions.
Step 2: Select a Permission Profile for the Task
Common profiles can be categorized into four types:
| Profile | Use Case | Network | File Writes |
|---|---|---|---|
read-only | Read-only analysis, code review, impact assessment | Off | Denied |
workspace-edit-no-net | Standard refactoring, adding tests, documentation changes | Off | Within workspace |
workspace-edit-net-allowlist | Needs access to package sources, GitHub, or model APIs | Domain allowlist | Within workspace |
privileged-manual | Deployment, cloud resources, databases, cross-repo modifications | Step-by-step approval | Step-by-step approval |
Do not let all tasks fall into
danger-full-access. The Codex documentation also clearly states that this mode removes filesystem and network boundaries and should only be used when full access is genuinely required.
Step 3: Record Commands and File Diffs During Execution
Every shell invocation should be logged:
- Command, working directory, environment variable summary
- Exit code, truncated stdout/stderr, duration
- Complete diff of file modifications (not just “task succeeded”)
If the agent modifies lock files, generated files, migration scripts, or CI configurations, mark them for mandatory human review.
Step 4: Make Network Access Observable
All network requests should at least record: target domain, port, protocol, whether it hit an allow/deny rule, the source command, and timestamp. For package managers, requests can be categorized by source (e.g., npm, pip, cargo, maven, apt) to facilitate subsequent supply chain issue investigation.
Step 5: Apply a Merge Gate Before Output
Do not treat the workspace state as the final result immediately after the agent completes. It should first pass through a merge gate:
- ✅ Is the diff only within allowed directories?
- ✅ Does it contain secrets, tokens, certificates, or personal information?
- ✅ Did tests pass? If not, is there an explanation?
- ✅ Are there new suspicious dependencies or postinstall scripts?
- ✅ Are deployment, permission, network, or billing-related configurations modified?
- ✅ Is there a large-scale refactoring beyond the task scope?
Only after passing the gate should a PR be generated, a commit be made, or the user be asked for confirmation.
Applicable Scenarios
This approach is suitable for the following scenarios:
- Teams preparing to integrate a coding agent into real repositories, not just for generating code snippets.
- Teams wanting the agent to automatically fix bugs, add tests, perform dependency upgrades, or handle CI failures, but without reading secrets or accidentally modifying production configurations.
- Enterprises with multiple repositories, multiple permission levels, and various task types, needing to configure different agent permissions per project, team, or environment.
- Platform teams building their own coding agent and needing a unified set of runtime boundaries for local CLI, Web IDE, cloud runners, and enterprise auditing.
Common Misconceptions
Misconception 1: A Strong Enough Model Doesn’t Need a Sandbox
The stronger the model, the more it needs boundaries. A powerful model is more capable of completing complex operations and is also more likely to chain multiple low-risk steps into a high-risk outcome. Permission design should not rely on model self-restraint.
Misconception 2: Containers Equal Security
Containers are just a basic isolation layer. Without minimal mounts, non-root users, network restrictions, resource limits, seccomp/capabilities, and audit logs, a container can still expose a large attack surface.
Misconception 3: More Approvals Mean More Security
Too many approvals lead to user fatigue, eventually causing them to disable protections. A better approach is to let low-risk actions execute smoothly within the sandbox and only trigger approval for cross-boundary actions.
Misconception 4: Only Shell Commands Matter, Not File Edits
Many risks don’t occur through shell commands but through file modifications. Examples include modifying CI configurations, writing deployment scripts, changing dependency versions, or generating hidden configuration files. File diff gates and path permissions are equally important.
Go-Live Checklist
Before going live, at least check the following items:
- Are there four profiles: read-only, workspace-writable, network-allowlist, and high-privilege approval?
- Is reading
.env, secrets, certificates, cloud credentials, and production configurations denied by default? - Is default access to the user’s home directory, sibling repositories, and system-sensitive paths prohibited?
- Is network access disabled by default, or at least restricted to only the domains required by the task?
- Is there separate approval for localhost, private network ranges, Docker socket, and Kubernetes configurations?
- Are every command, exit code, file diff, network access, and approval action logged?
- Can the workspace be rolled back on task failure or user rejection?
- Are execution time, process count, disk, memory, and output size limited?
- Are deployment, permission, CI/CD, and dependency upgrades marked as high-risk modifications?
- Are there red-team test cases for the agent reading secrets, writing across directories, accessing internal networks, and deleting files?
FAQ
Will a coding agent sandbox reduce efficiency?
It adds some boundary design cost, but it doesn’t necessarily reduce daily efficiency. Low-risk tasks execute automatically within the workspace; only high-risk actions require approval. Compared to asking for confirmation on every command, this model is better suited for long-term use.
How granular should the network allowlist be?
In production, it’s recommended to differentiate at least by task type: no network for standard code editing; allow package sources and artifact registries for dependency installation; allow model APIs for model calls; require separate approval for release-related tasks. Do not default to allowing * unless it’s a clearly designated temporary debugging environment.
When is full access appropriate?
Only when the task explicitly requires full filesystem or network access, and the execution environment is temporary, disposable, contains no sensitive credentials, and has no connectivity to production networks. Full access should never be the default for real development machines or enterprise repositories.