Table of Contents
- What agent sandboxing should protect
- Map the job to specific failure cases
- Choose the runtime around the workload
- Give each job a deliberate filesystem
- Restrict outbound access before untrusted execution
- Keep powerful credentials outside the worker
- Bound execution, retries and public entry points
- Test the boundaries, then test the useful work
- Price the boundary you actually need
- Frequently asked questions
- Does sandboxing prevent prompt injection?
- Is a Docker container enough for an agent?
- Can an agent use the internet inside a sandbox?
- Should every tool call create a fresh sandbox?
Do not index
Do not index
Agent sandboxing limits what an AI agent can read, change, execute and contact while it works. A useful setup combines an isolated runtime with explicit file, network, credential and action permissions. Agent37 provides gVisor sandboxes and full VMs for running agents, but your application still needs to decide what each agent is allowed to do.
That distinction matters when an agent reads an unfamiliar repository, follows a web page or installs a dependency. You want it to complete the task without handing that task access to everything your company owns.
What agent sandboxing should protect
Start with a concrete job: an agent receives a repository, edits a feature and runs tests. It needs the project files, a compiler and enough resources to finish. It probably does not need production database credentials, access to another customer's workspace or permission to deploy.
Write those boundaries down before choosing infrastructure. A sandbox policy should answer four questions: what enters, what runs, what can leave and what survives afterward.
A prompt telling the agent to behave is useful guidance. It is not the enforcement mechanism. A shell command, dependency script or subprocess can act on anything the runtime actually permits, regardless of your prompt.
Anthropic's sandboxing explanation describes why filesystem restrictions and network restrictions need to work together. Protecting files while allowing unrestricted outbound communication leaves a different gap from blocking the network while exposing sensitive local data.
Your goal is a bounded workspace where routine work can proceed with fewer interruptions, while consequential actions cross an explicit approval boundary.
Map the job to specific failure cases
Avoid a policy that only says βrun in a container.β Describe the damage you want to prevent and the control that addresses it.
Failure case | Control to design | What to verify |
A dependency deletes project files | Disposable working copy and retained source | The original repository stays recoverable |
A tool reads another customer's data | Separate workspace and scoped access | Cross-customer reads fail |
An injected instruction uploads a secret | Remove secrets and restrict outbound access | An unapproved destination is unreachable |
A test keeps spawning work | Resource limits and a job deadline | The supervisor can stop the entire job |
A generated change reaches production | Separate deployment authority | The execution worker cannot approve itself |
These are suggested acceptance criteria, not claims that one product automatically implements the whole table.
Include ordinary mistakes as well as hostile input. An agent can install the wrong package, follow an outdated command or retry a successful operation after losing the response. Designing for those cases makes the workflow easier to recover even when nobody is attacking it.
Choose the runtime around the workload
Conventional Linux containers use namespaces and other kernel controls while sharing the host kernel. Docker's security documentation also highlights the daemon and container configuration as security considerations. Giving a worker access to the host Docker socket changes the authority it has, regardless of the container label.
gVisor adds a userspace application kernel between the workload and host. It is neither an ordinary shared-kernel container boundary nor a full guest Linux VM. Its compatibility documentation recommends trying the actual workload because not every Linux feature is available.
On Agent37, standard gVisor sandboxes cannot run a Docker daemon. Choose a full VM when the task needs Docker, Compose or the VM's kernel capabilities. A VM changes the execution boundary; it does not remove the need to scope credentials and external actions.
For the architectural tradeoffs, read our microVM vs container guide. For your decision, test the real build, browser or toolchain before moving a whole queue of agents to it.
Give each job a deliberate filesystem
Treat the workspace as an input to the job, not a copy of your entire development machine.
For a coding task, stage the requested repository at an identified revision. Exclude local credential files, unrelated repositories and personal configuration. Put generated artifacts in a known output directory so a reviewer can see exactly what the agent produced.
Use read-only access for material the job only needs to inspect, where your runtime supports it. Keep a separate writable area for builds, caches and temporary files. Do not assume that naming a directory βworkspaceβ prevents a process from reading other paths.
Choose the reuse boundary deliberately. A persistent workspace can save setup time for repeated work on one project. Reusing it across unrelated customers introduces stale files, caches and credentials that a fresh job may inherit. A practical default is to separate customer workspaces and recreate disposable execution environments when the trust context changes.
Also decide what happens to the result. Returning a patch for review grants less authority than writing directly to a protected branch. Save the task's starting revision, resulting diff and test output together. That makes the work understandable without trusting the agent's summary of its own actions.
Restrict outbound access before untrusted execution
A worker that can reach the internet can contact more than your model provider. Decide whether this job needs networking during execution, or only while preparing its dependencies.
Agent37's network controls default to
allow-all. You can set deny-all, or an allowlist of IPv4 addresses and ranges. Domain names and IPv6 are not accepted by that field. The policy controls outbound connections; it does not close inbound instance URLs or public ports.For an offline execution job, the documented policy update looks like this. Replace
INSTANCE_ID with your instance identifier and keep the API key in your backend environment:curl --fail-with-body -X PATCH \
"https://api.agent37.com/v1/instances/INSTANCE_ID" \
-H "Authorization: Bearer $AGENT37_API_KEY" \
-H "Content-Type: application/json" \
-d '{"network":"deny-all"}'Wait for a successful policy response before launching the untrusted step. The docs distinguish an applied policy from a
503 try_again response, where the saved change is still propagating.deny-all also blocks DNS. Agent37's managed model and tool services are unavailable under either deny-all or an IP allowlist. Keep model orchestration outside that worker, or verify a separately authorized endpoint and its required connectivity. An IP allowlist is not a domain allowlist, so do not paste a model provider's hostname into it and assume the policy works.Keep powerful credentials outside the worker
Separate the program that decides what work may run from the program that executes untrusted code. The first can hold narrowly scoped service credentials. The second should receive only what this particular task requires.
For example, let a backend fetch the requested repository and stage it for the agent. If the task ends with a patch, it needs no production deployment credential. If a later step needs to publish, have a separate authorized service validate the artifact and perform that action.
This follows the least-privilege and high-impact-action controls in OWASP's agent security guidance. An allowlisted tool name is not enough when its arguments can select an arbitrary customer, destination or resource.
Agent37's environment variables are write-only through the instance API, but they are still delivered to the running workload. That protects against reading them back through that API, not against code inside the instance using them. Do not place your workspace control key there merely because it is convenient.
Treat exported logs and artifacts as possible secret outputs, too. Review what leaves the worker, and revoke temporary credentials when their job ends.
Bound execution, retries and public entry points
Set CPU, memory, disk and job-duration limits according to the task. A short lint job and a large dependency build need different budgets. Record failures separately from completed work so a retry does not accidentally become an endless loop.
The distinction between an HTTP timeout and a stopped job is especially important. Agent37's exec endpoint can time out while the command continues running. A blind retry can start another copy. Use a job identifier and inspect the existing process or result before retrying uncertain execution.
Also inspect the command's
exit_code. An HTTP success means the command ran, not necessarily that the tests passed.Inbound exposure needs its own review. An Agent37 public port is reachable without a platform credential. Use application authentication for sensitive services, verify webhook signatures where applicable and avoid making a terminal public as a shortcut. An outbound deny policy does not replace those protections.
These controls belong in your application flow so that agents cannot silently increase their own limits or expose a new service while attempting to finish a task.
Test the boundaries, then test the useful work
A sandbox evaluation needs both negative tests and a successful real task. Blocking everything is easy; allowing the necessary workflow with clear limits is the useful result.
Use harmless fixtures and a staging environment. Place a dummy secret outside the approved workspace and check that the worker cannot read it. Attempt an outbound request to a destination you control but have not approved. Confirm that the intended package or model connection still works under the chosen policy.
Then test the workflow itself:
- Run the ordinary build and inspect its actual exit status.
- Change the network policy and confirm when enforcement takes effect.
- Interrupt a job and verify that recovery does not duplicate its external actions.
- Start a new customer task and check that previous files and credentials are absent.
- Export an artifact and inspect it for unintended files or sensitive values.
- Restart the environment and confirm which required files remain.
Record the template version, resource shape and policy with those results. Otherwise, a later image change may invalidate your earlier check without anyone noticing.
The examples here are a validation plan, not a claim that we ran this suite against every runtime. Apply it to the exact configuration you intend to deploy.
Price the boundary you actually need
Compare the infrastructure cost after identifying the required runtime. Agent37's standard rates are $0.80 per vCPU, $0.70 per GB of RAM and $0.09 per GB of disk per 730-hour month, metered by the minute.
At 2 vCPU, 4 GB RAM and 4 GB disk, that is $4.76 for 730 running hours. A full VM at that same shape is $11.36, reflecting its 2.5x compute rate. These are infrastructure estimates, not model or tool budgets. Check the current pricing and assumptions.
An awake worker bills compute even while waiting. Stopping or sleeping pauses compute, while retained disk continues billing. Auto-sleep must be enabled, and durable output should live on disk because memory restoration is not guaranteed.
Start with one representative job. Explore Agent37 sandboxes, apply its access policy and measure the completed workflow before expanding concurrency.
Frequently asked questions
Does sandboxing prevent prompt injection?
It can limit what a compromised agent can do. It does not make instructions from untrusted content trustworthy, or prevent damage through permissions you deliberately granted. Keep approval and authorization checks outside the untrusted execution worker.
Is a Docker container enough for an agent?
That depends on the workload and threat model. Review shared-kernel exposure, mounts, daemon access, credentials and networking. Choose gVisor or a VM when its isolation and compatibility fit your requirements, then verify the configured boundary.
Can an agent use the internet inside a sandbox?
Yes, if its policy permits it. Agent37 allows outbound internet access by default. Restrict access deliberately, and verify the connections required by the workload before assuming that an allowlist supports it.
Should every tool call create a fresh sandbox?
Not necessarily. A fresh environment helps separate unrelated jobs, while a persistent workspace can suit repeated work within one project. Choose based on the trust boundary and retained state, rather than making every tool call pay the same setup cost.
