Infrastructure Review Stack

Sandbox Code Execution Models Across Runtimes

Four isolation primitives power AI code execution, each with different security and speed tradeoffs.

Senior Writer · · 12 min read · Updated
Cover illustration for “Sandbox Code Execution Models Across Runtimes”
Code Execution Sandboxes Compared · August 18, 2026 · 12 min read · 2,736 words

Sandbox execution models decide how AI agents run the code they write, and it comes down to four building blocks: standard containers, Firecracker microVMs, gVisor, and WebAssembly. Pick wrong for a given workload and you won't find out at design time. You'll find out three months in, usually as a security hole or a wall you hit at 2am when traffic spikes. I've spent enough time debugging sandbox escapes and cold-start complaints to know the theory always sounds cleaner than the incident report.

Gartner projects that 40% of enterprise applications will feature task-specific AI agents by the end of 2026, up from under 5% in 2025. GitHub logged a billion commits in 2025, and a growing chunk of that code got written and run by a model instead of a person typing line by line. That's not a forecast, that's infrastructure already carrying weight. The people building it are making these tradeoffs whether they've sat down and thought them through or not.

The four isolation primitives that all sandbox execution models build from

Every sandbox platform on the market builds on one of four isolation approaches, or some layered mix of them. A fifth, Microsoft's LiteBox, a Rust-based Library OS, started coming up in conversation in early 2026, but it's nowhere near deployed widely enough to count yet. So the count stands at four, for now.

Standard containers, the Docker and runc kind, share the host kernel across every workload on that machine. Isolation comes from Linux namespaces and cgroups, not hardware, which means the boundary is a software one, and software boundaries leak. CVE-2024-21626, nicknamed "Leaky Vessels," was a file descriptor leak in runc that let a container reach into the host filesystem. It sat in production infrastructure for a while before anyone caught it. Most people building this stuff agree that a standard container by itself isn't enough for running AI-generated code. It's a starting point, the layer other primitives get stacked on top of, not the whole answer.

Firecracker takes a different approach. Each workload boots its own guest kernel on top of KVM hardware virtualization, so the boundary protecting the host is the CPU's virtualization layer, not a namespace. AWS built it in Rust, and it's what runs Lambda and Fargate. Cold start lands around 125 milliseconds, kernel boot and device init included, which is genuinely fast for something spinning up a full guest kernel. The isolation is the strongest of the four. You pay for it in boot time and per-VM memory overhead, and there's no getting around that trade.

gVisor sits in the middle, and "middle" does a lot of work in that sentence. It runs a component called Sentry that intercepts every syscall the workload makes, handling most of them in userspace and passing through only a small slice of actual syscalls to the real kernel. It covers most Linux syscalls this way, but not all of them, so systemd, Docker-in-Docker, and some networking features might just not work. Runtime overhead sits noticeably above a native container. You get more isolation than a raw container without a full guest kernel underneath, but the missing syscall coverage is the kind of gap that stays invisible right up until one workload needs exactly what isn't there.

WebAssembly works on a completely different model. Isolation isn't a kernel feature here at all, it's a property of the language runtime. Linear memory gets bounds-checked on every access, there are no ambient syscalls, and a WASM module only talks to the outside world through host functions it was explicitly handed permission to import. Startup runs in microseconds, a different category entirely from the other three. But the constraint is hard: WASM only runs code compiled to the WASM target. No native Linux binaries, no fork or exec through WASI. Python runs inside WASM through Pyodide, and packages like NumPy work only because someone specifically ported them to compile that way. For stateless, compute-heavy tasks, that's a fine trade. For an agent that needs networking, threading, or a session that lasts more than a few seconds, friction shows up fast.

None of these four are locked into standalone use, either. Plenty of platforms run gVisor inside a container, or run microVMs with container-compatible images, tuning the security-to-performance curve to whatever a given workload actually needs.

Table: The Four Isolation Primitives Compared. Compares Isolation Mechanism, Startup Latency, Isolation Strength, Compatibility, and 2 more by Standard Containers, Firecracker microVMs, gVisor and WebAssembly.

How the threat model for AI-generated code differs from traditional untrusted-code scenarios

Traditional sandboxing assumes a known adversary: a person wrote code that might be malicious, and the sandbox's job is to keep it contained. AI agent workloads split that into two separate layers, and treating them as one problem is where a lot of early sandbox designs went sideways.

The first layer is execution isolation, same as it's always been. The code an agent writes might be buggy, might eat every CPU cycle it can grab, or might be malicious because the agent got instructed, deliberately or not, to do something harmful. Here's the wrinkle traditional threat models never had to deal with, though: the agent might probe for an escape path not out of malice at all, but as an accidental side effect of trying to finish some completely unrelated task. It stumbles into the boundary on its way to doing something else entirely.

The second layer sits above the sandbox, at the agent level. Prompt injection and tool poisoning corrupt what the agent decides to do before any code ever reaches the sandbox. PromptArmor disclosed a vulnerability in early 2026 in Snowflake's Cortex Code CLI, where indirect prompt injection combined with weak command validation slipped past human-in-the-loop approval entirely, leading to arbitrary code execution and unauthorized access to cached credentials. The sandbox did exactly what it was told. The problem sat upstream, in what the agent was told to do in the first place.

Supply chain risk piles on top of that. The Shai-Hulud campaigns in late 2025 compromised hundreds of npm packages, specifically targeting AI agent workflows. Agents that run npm install or pip install at runtime are sitting on an attack surface that's already been exploited, not a hypothetical one someone's warning you about in advance. Model capability keeps moving the goalposts too: frontier models' success rate on apprentice-level cybersecurity tasks went from under 10% in late 2023 and early 2024 to somewhere around 50% in 2025. A sandbox built around what a 2023 model could pull off is measurably weaker against a 2026 model, even if nothing about the sandbox itself changed at all.

One more wrinkle worth sitting with, because it's easy to miss. Research has found that LLM-generated code patches, the "fix" a model writes for a bug, introduce new security vulnerabilities in roughly one out of every ten cases, even while successfully resolving the original issue. So the code you're sandboxing isn't just the agent's first draft. It's every repair attempt after that too, and each one needs the same containment as the original (a lighter touch because it's "just a fix" is exactly how you get burned).

The core tradeoffs: how isolation level, startup latency, statefulness, and compatibility trade against each other

Venn diagram: AI Sandbox Execution Models: WASM vs Firecracker. Compares WebAssembly and Firecracker microVMs; overlap: Shared Traits.

Four dimensions decide whether an execution model actually fits an agent workload: isolation strength, startup latency, statefulness, and compatibility. Isolation runs from hardware-enforced (microVMs) down through syscall-intercepted (gVisor), namespace-bounded (containers), to capability-constrained (WASM). Latency runs roughly the opposite direction, microseconds for WASM, seconds for a cold full VM. Statefulness is about whether filesystem and memory persist across invocations or get torn down every time. Compatibility is whether you can run arbitrary Linux binaries or only code compiled for a narrower target.

This isn't a straight line where more isolation always costs more latency, though. Firecracker hits 125 milliseconds precisely because it strips the VM down to bare minimum; a poorly configured container hauling around a bloated image can end up slower than that despite offering weaker isolation to begin with. WASM gets microsecond starts, at the cost of the entire native binary ecosystem you give up to get there.

Statefulness might be the dimension teams underweight most when picking a sandbox early on. An agent doing a real multi-step task (installing dependencies, writing code, running the test suite, fixing what fails, iterating again) loses all its progress on every ephemeral teardown. That's a direct tax on how long the task takes overall, paid again on every single cycle. And designing around statefulness isn't a primitive-level decision at all; it's a platform-level one, tied up in how snapshotting and resume actually work underneath.

Anthropic has found that sandboxing cuts permission prompts by 84%, removing a human bottleneck that agents otherwise learn to route around anyway. That number only holds up if the sandbox starts fast enough that agents aren't sitting idle waiting on environment setup before they can even begin. A great isolation model that takes three seconds to boot doesn't eliminate the bottleneck, it just moves it somewhere else in the pipeline.

No single primitive wins on all four dimensions at once, and that's exactly why the platform layer (how these primitives get combined and tuned) ends up mattering as much as which primitive gets picked in the first place.

How current sandbox platforms implement these tradeoffs in practice

Platforms differ not just in which primitive they lean on, but in how they stack primitives together and what they're actually optimizing for. Worth walking through a handful of them, because the differences show up in ways a feature comparison table tends to flatten out.

Northflank runs over 2 million isolated workloads a month and takes a genuinely adaptive approach, using both Kata Containers (microVM-based) and gVisor, choosing the isolation level per workload instead of committing to one primitive across the board. It supports BYOC deployment across AWS, GCP, Azure, and bare metal, along with GPU support, unlimited session duration, and OCI-compatible images.

Vercel Sandbox runs temporary Linux microVMs, giving hardware-enforced isolation aimed squarely at agents and code execution inside the Vercel ecosystem. Strong fit if you're already building on Vercel. Less so if you need persistent state or your own compute sitting underneath it.

Cloudflare Sandboxes build on Cloudflare Containers and Workers, running isolated Linux execution at the edge with a TypeScript-first API that also supports Python and Node.js. The edge-native angle is the real differentiator, genuinely useful for latency-sensitive, geographically distributed work, though the Python and Node constraint limits how general-purpose it can be for agents that need other languages.

Microsandbox is the self-hosted option: open-source, first released in May 2025, with roughly 3,300 GitHub stars since launch. It uses microVM isolation through libkrun and gets sub-200ms startup, and because it's self-hosted, teams keep full control over their own infrastructure. Fits teams with real operational capacity, the ones who want maximum isolation and data sovereignty without depending on a managed vendor sitting between them and their workloads.

Blaxel takes an interesting angle on the statefulness problem specifically: sandboxes can stand by indefinitely at zero compute cost and resume in under 25 milliseconds with filesystem and memory state fully intact. It's optimizing narrowly for the resume side of the tradeoff rather than chasing the fastest cold start overall, which is a different bet than most of the field is making.

The pattern across all of this: platforms leading with isolation strength, microVM-first designs, accept a slightly higher startup cost as the price of that boundary. Platforms optimizing for startup speed and statefulness tend to reach for layered or per-sandbox isolation instead of leaning on one maximally hardened primitive. Nobody wins every dimension at once. The real question is which tradeoffs your specific workload can absorb without that absorption turning into an actual incident later.

What production scale actually reveals about execution model assumptions

Scale exposes assumptions that looked fine in a demo and quietly fall apart under real load. A few seconds of cold-start latency doesn't matter much for one sandbox running once. But an agent task that spawns dozens of sandboxes in sequence, or in parallel, can stall for minutes on infrastructure delay alone, and suddenly the bottleneck isn't model inference anymore, it's plumbing nobody was watching.

Statefulness debt shows up the same way. Ephemeral teardown means reinstalling dependencies and rebuilding context on every single invocation, and that cost scales right alongside task complexity. A simple one-shot script barely notices it. A multi-step agent workflow running the install-test-iterate loop dozens of times pays that tax every round, though, and it adds up faster than most teams expect going in.

Concurrency behaves differently by isolation model too. Shared-kernel platforms hit noisy-neighbor problems earlier than designs giving each sandbox its own kernel, because one workload's resource spike bleeds into another's performance in a way it simply can't when the kernels are actually separate. The gVisor overhead sounds tolerable on a single sandbox. Multiply that across a few thousand concurrent sessions, though, and it starts bending your infrastructure cost curve in a direction that gets hard to ignore.

WASM's statelessness constraint becomes more visible at scale, not less. Microsecond starts are genuinely appealing on paper, but an agent doing real iterative work (installing something, running it, checking the result, adjusting) needs state to carry across those steps. WASM doesn't hand you that for free. It takes real engineering stacked on top, which undercuts some of the simplicity that made it attractive to begin with.

Autoscaling diverges by model as well. Container-based platforms tend to scale faster because image layers get cached and reused. MicroVM-based platforms scale more securely, but either need pre-warmed capacity sitting ready, or have to accept that cold-boot penalty on every cold path. Each one is built for a different failure mode. Neither is wrong exactly, they're just aimed at different worst days.

There's a quieter architectural point worth raising here too. Keeping agent logic and sandboxes on the same infrastructure removes network roundtrip latency from every code execution call. That barely registers when an agent makes one or two calls total. It matters quite a bit when an agent makes dozens per task, which, for anything nontrivial, is closer to the norm than the exception.

The supply chain risk from campaigns like Shai-Hulud doesn't shrink with scale, either. It grows with it. The more sandboxes out there running npm install or pip install at runtime, the bigger the surface for a compromised package to slip through unnoticed. Execution isolation, however strong, doesn't substitute for checking what's actually inside the dependency you just pulled down.

How to match execution model to AI agent workload type

The question of which primitive is "best" doesn't have a stable answer independent of what you're actually running. What matters more is which primitive's tradeoffs your workload can absorb, and which ones would break it outright the first week in production.

A short-lived, stateless compute task, something taking an input, running a fixed transformation, returning an output, is a good match for WASM. The microsecond start time is a real advantage there, and the lack of persistent state costs nothing, because there was never anything worth persisting in the first place.

An agent running a genuine multi-step workflow (writing code, installing packages, running tests, fixing failures, iterating) needs statefulness far more than it needs the fastest possible cold start. That points toward platforms built around persistent workspaces or fast resume. Losing context on every teardown defeats the entire premise of an iterative agent loop before it even gets going.

Workloads touching sensitive data, financial calculations, credentials, anything where a container escape would be a genuinely serious event, justify the overhead of microVM isolation or gVisor even if it costs latency or memory. That's exactly what hardware-enforced boundaries exist for, and it's the right place to spend that cost rather than economize on it.

High-concurrency agent platforms serving many users at once need to work through the per-sandbox overhead question before it turns into a cost or performance emergency, not after. What runs fine at ten concurrent sandboxes can behave very differently at ten thousand, and the primitive that felt like the safe, boring choice early on is sometimes exactly the one that stops scaling gracefully once real traffic shows up.

None of this is a permanent decision, and none of it is free. But knowing the four primitives, how the AI threat model differs from the one sandboxes were originally built to handle, and how these tradeoffs actually play out past the demo stage. That's a real basis for choosing, rather than just inheriting whatever the last team happened to default to.

More in Code Execution Sandboxes Compared