An isolated, disposable environment where code of unknown provenance can execute without reaching anything that matters.
The Docker chapters in this track teach containers as packaging — a way to ship a service. This chapter teaches the same technology as a boundary, pointed the other way: keeping code your agent just wrote away from your laptop, your credentials and your production host. → Firecracker microVMs, what a container does and does not isolate, and the small set of rules that make an execute-this-code loop survivable. → It also carries a live lesson in dependency risk: one of the best-known sandboxes in this space moved its core development into a private codebase mid-2026.
An agent that writes code eventually wants to run it. This is where — a microVM with no credentials, a narrow filesystem, no network unless asked, and a hard time limit. Containers as a security boundary rather than a packaging format, and the difference between the two.
→Say precisely what a container isolates and what it does not
→Run agent-generated code in a microVM instead of on your host
→Give a sandbox the narrowest filesystem and network it can still work in
→Return results from a sandbox without handing it your credentials
→Set a wall-clock and resource ceiling so a loop cannot run all night
→Judge whether an open-sourcesandbox is still open before you depend on it
1.3When to reach for it
Any loop where a model writes code and something runs it: data analysis agents, self-testing agents, anything with an execute tool.
1.4Key parts
A microVM or hardened container, a scrubbed environment, an explicit network policy, a resource and time ceiling, and a result channel that carries data rather than access.
1.5Free vs paid
The sandbox runtime is open source and self-hostable; the hosted version is metered per second of execution. Self-hosting trades money for an operational burden.
1.6Watch out
A container shares the host kernel. That is fine for packaging and thin for adversarial code — which is what "code my agent wrote from a web page it read" is.
2Lessons 7
2.1Explain the isolation differences between containers and microVMs
A microVM runs its own kernel instance, while a container shares the host kernel, giving microVMs a stronger security boundary for untrusted code.
Show how kernel isolation differs between containers and microVMs
Launch a docker runcontainer that executes uname -r
Observe the kernel version printed inside the container
Start a firecracker microVM that runs uname -r
Observe the independent kernel version printed by the microVM
You'll see The Dockercontainer displays the host's kernel version, whereas each Firecracker microVM shows its own separate kernel version
TakeawayContainers share the host kernel and cannot protect against kernel exploits; microVMs provide a true isolation boundary with their own kernels
Check How does the difference in displayed kernel versions illustrate the security advantage of microVMs over containers when running untrusted code?
Cost Free to reason about — this lesson is the vocabulary the rest of the chapter builds on.
2.2Run agent‑generated code inside a microVM
The Sandbox.create() method starts a Firecracker microVM that can run commands via sandbox.commands.run(), returning structured results.
Execute agent‑generated code inside an isolated Firecracker microVM using the E2B SDK
Open the e2b.dev site and register for an account
Generate an API key, export it as E2B_API_KEY in your shell
Install the Python SDK with pip install e2b
Write a script that calls Sandbox.create() then runs sandbox.commands.run('python3 -c "print(2+2)"')
Run the script and view the result object containing stdout, stderr and exit code
Terminate the microVM with sandbox.kill()
You'll see The commands.run() call returns a JSON‑like result showing stdout = 4, empty stderr and a zero exit code
Takeaway Each execution runs in its own microVM so no state or credentials persist between runs
Check In what way does creating a sandbox with Sandbox.create() and invoking commands.run() keep agent‑generated code from affecting the host system?
CostSelf-hosted: your own compute, Terraform-managed. Hosted: metered per second of sandbox runtime, billed to the E2B account behind your API key.
2.3Configure a sandbox with deny‑by‑default network and scoped filesystem
A deny‑by‑default network blocks all outbound traffic unless hosts are explicitly added to the network.allow_out list.
Configure an E2B sandbox so that only whitelisted hosts can be contacted and no other files exist inside it
Call Sandbox.create without extra mounts to get a fresh environment
Pass allowInternetAccess=False to Sandbox.create to disable all outbound traffic by default
Add required destinations to the network.allow_out allow‑list in the sandbox configuration
Attempt a request to an unlisted address and verify it fails immediately
You'll see The outbound request to the non‑whitelisted host is rejected instantly, while a request to a whitelisted host succeeds
Takeaway Start with a blanket deny and then add narrow allowances because allow rules override the default block
Check What happens to network connections when you disable internet access globally and then explicitly whitelist hosts in an E2B sandbox?
Cost No extra infrastructure — this is a parameter on the same Sandbox.create() call, free either way.
2.4Run untrusted code and retrieve its output safely
Keeping credentials out of the sandbox and only returning plain JSON output ensures privileged actions stay in trusted code.
Separate secret handling from sandboxed execution so that only safe results are returned
Create a sandbox with Sandbox.create using an empty envs dictionary
Run the agent‑written script inside the sandbox via sandbox.commands.run and capture its stdout/stderr
Read any output files produced by the sandbox with sandbox.read_file after execution
Pass the captured JSON result to trusted code that holds credentials and performs privileged operations
You'll see The sandbox returns a plain JSON payload while its environment contains no secret values
Takeaway Never expose real credentials inside the sandbox; let trusted code handle any privileged work
Check Why must credentials stay outside the sandbox and only JSON results be passed back after running agent‑generated code?
Cost No added cost — this is how you call the same SDK, not a different one.
2.5Configure a sandbox timeout that stops runaway loops
The timeoutMsparameter sets a hard execution limit, aborting the microVM when the time expires.
Enforce a maximum runtime so runaway loops are terminated automatically
Create a sandbox with Sandbox.create({ timeoutMs: 60000 }) to set a one‑minute limit
Optionally call sandbox.setTimeout(120000) if a longer run is needed for a specific task
Run a script that contains a loop exceeding the configured limit
Observe the sandbox aborting the process when the timeout is reached
You'll see The sandbox stops mid‑loop as soon as its timeout expires, and subsequent commands fail immediately
Takeaway Match the sandbox timeout to the actual work required rather than relying on an unlimited ceiling
Check How does a sandbox’s timeout protect against runaway code, and what observable behaviour occurs when the limit is hit?
Cost None beyond the sandbox time you would have used anyway — a tight timeout only ever removes wasted runtime, never useful runtime.
2.6Verify a sandbox project's maintenance status yourself
The maintenance status paragraph in a repository’s README indicates whether the project is actively maintained or deprecated.
Verify that a sandbox‑related library you depend on is still actively maintained
Navigate to the project's page on GitHub in your browser
Click the README tab to view its contents
Scroll until you find the maintenance status paragraph
Record any statements about ongoing development, deprecation or migration to a private codebase
You'll see The README displays a clear statement about the project’s current maintenance status
Takeaway Always check the project's own README for maintenance information before trusting it in your sandbox workflow
Check Which part of a GitHub repository should you examine to determine if its sandbox tool is still actively maintained?
Cost A few minutes to read a README before you build on it — far cheaper than discovering a security fix will never land.
2.7Run agent‑written code safely
MicroVM isolation, credential‑free environments, deny‑by‑default networking, resource caps and verified open‑source tools together form a defence‑in‑depth sandbox for untrusted scripts.
Run an agent‑generated script only after it passes every safety gate you control
Select Firecracker microVM as the execution target to guarantee kernel isolation
Inspect the sandbox’s envs list and ensure no real credentials are present, moving them to trusted code outside the sandbox
Set the default network policy to deny all outbound traffic using the network rules control, then add explicit allow entries for required hosts only
Configure a matching execution timeout, and limit CPU and memory with the respective resource caps controls
Re‑open the sandbox tool’s README to confirm it remains open‑source before each deployment
You'll see The script is accepted only when it meets all five checks: microVM isolation, credential‑free envs, deny‑all network with allow‑list, tight resource limits and a verified open‑source sandbox
Takeaway Combining multiple independent safeguards blocks different attack vectors, making the overall execution safe
Check How do the combined checks of microVM isolation, credential‑free environments, deny‑by‑default networking, resource caps and README verification together ensure safe execution of agent‑written scripts?
Cost A few minutes of deliberate configuration per sandbox, reused across every task that shares the same template.
3You’ll know it worked 11 checkable outcomes in this chapter
✓The code runs inside the Fly machine and cannot access files or environment variables on your local laptop
✓The container exits with a clean exit code and no changes appear on the host filesystem or network interfaces
✓The function returns `(-1, '', 'Timeout')` for infinite loops and proper output for safe scripts
✓All new tests pass before the commit is merged, and CI reports zero failures
✓The agent refuses to generate code that violates rules defined in the nearest context file
✓Attempts by the code to perform privileged syscalls are blocked with permission errors inside the sandbox
✓Check the Worker logs for successful execution and confirm no external credentials were accessed
✓The payload can read /etc/passwd inside the VM but cannot see the host's password file or affect host processes
11 outcomes in all — one per recipe below.
4FAQ, Tips & How-to 11
one problem, one solution, one action
▸How-toEveryone
Run untrusted user code safely
Fly.io machines let you launch an OCI‑compatible image inside a lightweight virtual machine (Firecracker microVM). By packaging the execution environment in a Docker image and deploying it as a Fly machine, you isolate user‑provided code from your host, credentials, and production services.
A Dockercontainer can act as a digital prison that runs arbitrary Python code while preventing access to the host filesystem, network, and excessive resources. By pulling a minimal python:3.11-slim image and launching it with restrictive flags, any malicious behavior is confined and the container self‑destructs after execution.
Python's `subprocess.run` can launch the Docker command from a script, automatically applying a timeout and capturing stdout/stderr. This lets you programmatically evaluate untrusted code and return a uniform result tuple (exit_code, stdout, stderr) without manual CLI interaction.
Specific Docker run options (`--network none`, `-m <mem>`, `--cpus <cpu>`) provide a lightweight security boundary that stops most attacks: no outbound connections, limited RAM to prevent OOM, and CPU caps to kill infinite loops quickly.
Breaking each AI‑written change into tiny, test‑driven commits limits the blast radius of bugs or malicious behavior and makes reviews trivial. With a single focused test per commit you can instantly verify intent and catch regressions.
Placing a lightweight Gemini‑style context file in each project directory gives the agent a scoped style guide and security policy, preventing it from using unsafe patterns or accessing irrelevant resources.
Need to run AI‑generated scripts without risking the host
Unlike plain Dockercontainers, gVisor intercepts most system calls and runs them in user space, providing a stronger barrier that prevents the agent from escaping to the host kernel.
Static analysis (SAST/SCA) catches known patterns of vulnerability, while an adversarial AI agent can simulate attacks on business logic that static tools miss, giving a more complete security picture.
Cloudflare Workers (now called 'mode worker') provide a secure, browser‑enabled sandbox that isolates execution from your local machine and credentials. By deploying the agent’s code to this environment you get OS‑level separation, limited network access, and built‑in monitoring, making it safe to run code generated by the AI.
A Firecracker microVM runs a minimal Linux kernel in its own virtualized environment, providing hardware‑enforced isolation separate from the host OS. This prevents malicious payloads from accessing host files, credentials, or network resources while still booting in milliseconds.
Automating the creation, execution, and destruction of Firecracker microVMs ensures each user request gets a fresh isolated environment, eliminating state leakage and simplifying resource cleanup.