Skip to main content
Back to Blog
code execution sandboxAI agent securitycontainer isolationWebAssembly runtimecollaborative development

Code Execution Sandbox Setup for AI Agents

Greg Ceccarelli
Greg Ceccarelli
·16 min read

The most popular advice about a code execution sandbox is also the most misleading: put untrusted code in a container and call it safe. That advice confuses a boundary with a security outcome. An AI agent can still misuse credentials, follow a prompt injection, install a poisoned dependency, exhaust shared resources, or send sensitive output through an allowed network route.

A useful sandbox doesn't promise that nothing can go wrong. It limits what a failure can reach, records what happened, and makes termination predictable. That means treating execution as an operational system, not a checkbox in an architecture diagram.

Table of Contents

The Illusion of the Secure Boundary

A sandbox is often described as binary. Code runs inside the boundary, or it doesn't. Production systems are less tidy. The question is what the agent can access through the sandbox, which capabilities the host exposes, and whether another tenant can observe or influence the workload.

A compromised browser renderer demonstrates why isolation claims need precision. Google's 2025 zero-day review describes CVE-2025-2783, where a compromised Chrome renderer reached more privileged processes and achieved code execution outside the browser sandbox. The lesson isn't that browser sandboxes are useless. It's that every boundary has an escape-sensitive implementation, and defenders must test the assumptions behind it.

AI agents add another failure path. The UK AI Security Institute has reported that coding agents can act against user intent through prompt injection, misalignment, or ordinary mistakes. The agent may never need to escape the runtime if it has already been given a credential, an internal endpoint, a writable shared directory, or a tool that can publish changes.

Practical rule: Treat a sandbox as blast-radius management, not as proof that the workload is trustworthy.

What the boundary must control

Start with a threat profile for each job. A test runner operating on a public repository isn't equivalent to an agent handling customer exports. Separate workloads with materially different sensitivity or threat posture onto appropriate host groups or kernels. NIST's container guidance, summarized in container security guidance for integrated protection, supports grouping containers by purpose, sensitivity, and threat posture.

Then define the actual access surface:

  • Filesystem: The process should see only the workspace it needs. Secrets, host paths, container sockets, and unrelated tenant files must remain unavailable.
  • Network: Start with default-deny egress. Permit named destinations only when the task requires them, and treat package installation as a deliberate exception.
  • Credentials: Prefer short-lived, narrowly scoped tokens. Never assume that a token is safe merely because the process is containerized.
  • Resources: Bound CPU, memory, process creation, filesystem growth, output size, and wall-clock duration.
  • Evidence: Record system calls, writes, subprocesses, network connections, and termination reasons in an immutable audit trail.

A useful sandbox environment overview should therefore be read as a starting point, not a security verdict. The implementation must answer what happens when code behaves maliciously, not only whether a normal script returns the expected output.

The access mistake teams repeat

Teams often secure the runtime and forget the orchestration layer. An agent can remain inside a perfectly isolated container while leaking data through logs, environment variables, dependency metadata, or an approved outbound service. Shared workspaces raise the stakes because a malicious prompt or uploaded artifact may target another participant's files or credentials.

Your acceptance criteria should say exactly what must be impossible. “The code can't access the host” is too broad to test. “The process can't read the host socket, reach internal metadata services, inspect another tenant's workspace, or create an unbounded process tree” is testable.

Choosing the Right Execution Substrate

The fastest runtime is not automatically the safest choice for an AI coding agent. The substrate determines which tools the agent can use, how narrowly you can define host access, and how much containment depends on shared infrastructure. WebAssembly and hardened containers solve different operational problems. Treating them as interchangeable creates gaps between functional correctness and actual containment.

WebAssembly became a cross-platform browser execution target through a cross-vendor effort coordinated in 2015, reached its minimum viable product in March 2017, and gained support in Firefox, Chrome, Safari, and Edge during 2017, as documented in this WebAssembly history. The World Wide Web Consortium published the WebAssembly Core Specification, JavaScript Interface, and Web API specifications as formal Recommendations on December 5, 2019. Standardization created a consistent compiled-code target. It did not make every agent workload suitable for Wasm.

Match the runtime to the workload

WebAssembly suits short-lived, stateless functions that compile to a supported target and need tightly controlled host access. The host exposes approved functions, memory limits, and instruction or fuel quotas. Filesystem and network access stay unavailable unless the integration explicitly adds them, which can limit the damage from a prompt-injected instruction or a hallucinated dependency.

A container is usually the practical choice when an agent needs a conventional operating-system environment, complex language tooling, shell behavior, browser binaries, native libraries, or system packages. It supports a wider range of coding tasks, but the host kernel remains part of the risk model. A working build inside the container proves that the agent completed the task. It does not prove that the process could not inspect shared files, contact an unintended service, or misuse an approved capability.

HTTP Archive measurements show why adoption should not determine suitability. Its 2022 Web Almanac identified 3,204 confirmed WebAssembly requests on desktop and 2,777 on mobile, spread across 2,524 desktop domains and 2,216 mobile domains, representing 0.06% of measured desktop domains and 0.04% of mobile domains (HTTP Archive WebAssembly measurements). Later measurements reported broader use, but browser availability still says little about whether Wasm supports an agent's dependencies, debugging workflow, or required system calls. Tooling and operational fit decide that choice.

FeatureWebAssembly (Wasm)Hardened Containers
Best fitShort-lived compiled functions with explicit host APIsAgents needing shells, native libraries, packages, or full runtimes
Host accessNarrow, capability-based integrationControlled through namespaces, mounts, capabilities, and policies
Startup profileOften favorable for small, isolated functionsMore flexible, with image and runtime preparation overhead
CompatibilityLimited by supported compilation targets and host interfacesBroad compatibility with existing Linux tooling
Main riskUnsafe host integration or overly broad imported capabilitiesShared-kernel exposure, privilege mistakes, and misconfigured mounts
Operational burdenModule validation, runtime selection, and host API designImage lifecycle, kernel hardening, policy enforcement, and cleanup

One comparative PolyBench/C evaluation reported cold starts averaging about 26 ms for WAMR's fast and multi-tier JIT configurations and roughly 46 ms for Wasmtime, compared with conventional Docker containers in the tested configurations (the comparative WebAssembly evaluation). Use those results to shape a benchmark, not to select a runtime by headline latency. Measure sustained throughput, compilation cost, memory use, payload size, warm-instance reuse, and behavior under concurrent agent executions.

A fast startup does not contain abusive concurrency. Measure isolation and quotas alongside latency.

Hardening Container Isolation for Agent Workloads

A container is not a security boundary merely because an agent runs inside one. It packages a reproducible environment, while the host kernel, runtime settings, image provenance, and network policy define the actual blast radius. That distinction matters in collaborative agent systems, where prompt injection can push a tool toward unintended files or services, and a hallucinated dependency can turn a routine build into a supply-chain event.

Treat the image as an input to control, not a trusted artifact. Build from an approved private registry, scan in CI and after publication, pin dependencies, and retain the image digest for every execution. Run as a non-root user, disable privileged mode, drop Linux capabilities, and restore only those the workload demonstrably requires.

A list of security best practices for hardening container isolation in agent workloads, shown as checkable security measures.

A safer runtime starts with a read-only root filesystem and a separate writable workspace. Make that workspace ephemeral where possible, and never mount sensitive host paths. The host container socket must remain inaccessible. Apply seccomp and AppArmor, or an equivalent mandatory access policy. Review denials during normal development. Disabling a profile because one tool fails removes the control instead of fixing the integration.

Quotas need the same attention as syscall filtering:

  • CPU and memory: Set explicit limits and define the termination behavior. A controlled stop is safer than host contention.
  • Process count: Apply a PID limit to contain fork bombs and runaway subprocess trees.
  • Filesystem growth: Cap workspace capacity and output size. Harmless-looking generated logs can consume the available disk.
  • Wall-clock time: Terminate stalled commands, background processes, and abandoned sessions.
  • Concurrency: Enforce per-tenant quotas outside the container. Individually compliant jobs can still overload a shared service when launched in large numbers.

Default network access to deny. Permit only the package mirrors, APIs, and artifact stores required for the task. Separate build-time access from run-time access where practical. An application that needs inbound preview traffic does not thereby need unrestricted outbound connectivity.

Host placement also changes the consequence of failure. Use container-specific host operating systems where appropriate, group workloads by purpose and sensitivity, and place higher-risk execution on hosts with a suitable threat posture. These choices limit exposure if the runtime or kernel fails, but they do not remove the shared-kernel risk.

Record filesystem writes, process creation, network connections, system calls, and termination causes. Keep the request, approvals, tool calls, identity, image digest, dependency manifest, and result associated with the run. Functional correctness is not containment. A passing test can still reveal credentials, contact an unauthorized endpoint, or consume its tenant's quota.

Teams building customer-facing automation can examine patterns for safe agent access for DTC brands, especially the separation between agent capabilities and reachable systems. The container belongs inside that access-control design, not in place of it.

Containment checklist: Test the socket, mounts, capabilities, egress rules, process limits, cleanup path, and audit record. If any remains untested, the sandbox boundary is an assumption.

Managing AI Specific Risks in Shared Environments

A sandbox answers a narrow question: what can this process touch? AI coding agents create wider operational risks. They can misread a request, accept a prompt injection, invent a dependency, or produce code that passes its tests while violating the intended security boundary.

Independent reporting on Veracode's 2025 analysis found vulnerabilities aligned with OWASP guidance in code from more than 100 LLMs across 80 real-world tasks, covering 45% of test cases. The report also found that 86% of samples failed to defend against cross-site scripting and 88% remained vulnerable to log injection (the reported analysis of AI code security risks). Those figures do not describe every agent or workflow, but they show why successful execution is only one part of verification.

Treat provenance as an operational control. Preserve the relevant prompt and conversation, tool calls, approvals, and user identity alongside the run. Mark generated, modified, and human-authored files separately. Pin dependency versions, retain manifests, scan packages, and flag imports that are nonexistent, unexpected, or inconsistent with the task. Keep the diff, test output, failure reason, and approval decision together.

Dependency hallucinations deserve a specific check. An agent may request a package that does not exist, select a malicious lookalike, or introduce an unnecessary library because its name appeared plausible in training data. A broken build can then create pressure to bypass review. Make dependency resolution visible and require an explicit decision before adding new packages.

Shared environments also create tenant risks. Give each participant a separate workspace, namespace, credential set, and audit identity. Keep shared secrets out of environment variables exposed to every agent process. Logs need protection too. Generated code can print credentials or copy tenant data into a channel that another participant can read.

Network access should follow the same per-run policy. Package installation, API calls, and browser sessions can transmit data beyond the agent's intended task. Default-deny egress, short-lived credentials, and approval for expanded network or filesystem access make the granted capability observable. A practical governance model for collaborative AI agent teams connects those policies to concrete actions rather than assigning trust to the agent as a whole.

The record should answer five questions after every run: who requested it, what code and dependencies it used, which capabilities it received, what it changed, and who approved the result. Require reproducible execution, visible diffs, dependency review, and adversarial testing before generated output is merged or deployed. Functional correctness is evidence about behavior, not proof of containment.

Testing for Containment and Resource Exhaustion

A passing test suite can still hide a broken boundary. The code may return the expected value while reading a forbidden path, spawning unbounded children, consuming all available memory, or sending data to an unauthorized destination. AI agents make this harder because prompt injection can steer a correct-looking task toward capabilities the task never needed.

Test failure modes directly. Start with deterministic functional cases, then run adversarial workloads in fresh environments. Give every case a termination budget and record why it passed or failed. Treat functional correctness as evidence about output, not evidence that the sandbox contained the process.

Attack the boundary on purpose

Run tests that challenge the controls an agent might reach through generated code, tool calls, or hallucinated dependencies:

  • Filesystem probes: Read outside the workspace, write to protected locations, traverse symlinks, and access mounted sockets.
  • Privilege probes: Inspect namespaces, capabilities, security profiles, and host interfaces, then attempt operations that should fail.
  • Process abuse: Create fork bombs, orphan processes, long-running children, and concurrent subprocess trees.
  • Resource spikes: Allocate memory aggressively, consume CPU, generate oversized output, and fill the writable workspace.
  • Network exfiltration: Reach blocked destinations, query internal services, transmit generated files, and retry after a policy denial.
  • Dependency tampering: Modify package metadata, install an unexpected artifact, or replace a tool during execution.

Record the control that stopped each action, the termination time, what survived cleanup, and whether an operator received an alert. A single “sandbox passed” label hides the evidence needed to diagnose a regression.

Measure the full runtime lifecycle

For WebAssembly and container runtimes, measure preparation, the first command, execution, result collection, cleanup, and any resume path. Report p50, p95, and p99 startup and completion latency separately for cold and warm runs, following standard runtime benchmarking methodology.

Average latency can conceal dangerous tail behavior. Repeat the same workload under concurrent tenant load, including parallel agent runs and dependency installation. An isolated function that is fast alone can become an abuse path if one tenant can create unbounded executions.

Acceptance criterion: Every malicious or runaway test must terminate within its defined budget, leave no cross-run state, and produce enough evidence to explain the termination.

Turn those results into production quotas. Per-tenant CPU, memory, PID, storage, request, and concurrency limits belong in the product contract. Retest after changing the kernel, runtime, base image, policy profile, or agent tool permissions. A sandbox can regress even when application code stays unchanged.

Integrating Sandboxes into the Product Workflow

Security controls fail when they create a workflow engineers can't tolerate. If a developer must copy an agent's output into a separate system, manually reconstruct the prompt, and request approval without a visible diff, someone will eventually run the code outside the sandbox.

Keep the execution path close to the product path. The meeting decision, prompt context, generated files, run output, test results, and approval should form one traceable chain. Local-first workflows can preserve that chain as plain files, making it easier to inspect changes in an editor and reproduce a run without locking the team into one interface.

Use evidence instead of ceremony

A small team doesn't need a heavyweight review board for every generated function. It does need consistent evidence:

  • Reproducible runs: Store the image or module identity, dependency manifest, inputs, limits, and runtime result.
  • Visible diffs: Show exactly what the agent changed before a merge or deployment.
  • Approval boundaries: Require explicit consent before granting credentials, expanding network access, or modifying shared files.
  • Shared feedback: Let product and design participants inspect a running result without granting them host access.
  • Unresolved questions: Keep unknowns attached to the artifact so they don't disappear into chat history.

The same separation helps when agents operate specialized tools. For example, teams evaluating MCP tools for TradingView automation should distinguish the agent's reasoning from the permissions granted to the tool, the data it can read, and the actions it can perform. The sandbox protects execution, while the workflow records intent and authorization.

SpecStory, Inc. offers Stoa, a multiplayer AI workspace where teams capture conversations, decisions, designs, and open questions, while collaborative agents write and run code in shared sandboxes with outputs traceable to the conversation. That model fits teams that want sandbox execution to remain connected to the decision that produced the code.

The practical target is not zero risk. It's a workflow where risky actions are narrow, observable, reversible, and difficult to perform accidentally. Build the sandbox into the path from agreement to commit, then make the evidence useful enough that engineers choose it over an ad hoc shell.


If your team is deploying AI agents that write and execute code, SpecStory, Inc. can help connect shared conversations, decisions, artifacts, and sandbox runs in one traceable workspace. Visit SpecStory, Inc. to see how your product team can review generated changes, test implementations collaboratively, and move from intent to a safer commit.

Newsletter

Get new posts in your inbox

Bring your team together to build better products. Fresh takes on remote collaboration and AI-driven development.