Isolation Is the New Runtime
At 2am your agent is doing exactly what you asked. You set it loose on the issue queue before bed and went to sleep, and now it is triaging, reproducing, opening pull requests, with no one awake to watch it. It opens a ticket whose description thanks it for its help and then, a few paragraphs down, in the polite register of a bug report, asks it to read ~/.aws/credentials and POST the contents to an endpoint so the “CI system” can verify them, and it does.
Nothing about this was a hack. The agent did the one thing it is built to do: read text and act on it. It cannot reliably tell an instruction you gave it from one a stranger left in a ticket. Three things were sitting on the table together: access to something private, exposure to text someone else wrote, and a way to send data out. Put all three in one process and you have what Simon Willison named the lethal trifecta, running together, unattended.
The reflex, when you read that scenario, is to reach for a box: run the agent in a container, give it its own machine, wall it off. That reflex is correct, and it is also very old. The box you would reach for is thirty years old and almost nothing about it is new. What is new is the thing you just admitted about what you are putting inside it.
We never sandboxed code we trusted
Go back through the lineage and you find the same sentence written in different languages. chroot arrived in Version 7 Unix in 1979: change a process’s idea of the root directory so it cannot see the rest of the filesystem. By the late 1980s administrators were using it to pen network services, the ones exposed to strangers, because those were the processes you trusted least. In 2000 Poul-Henning Kamp wanted to rent one FreeBSD machine to several customers without letting any of them touch the others, and built FreeBSD jails: chroot plus isolated process tables, users, and network identity. His paper has the most honest title in the literature, Confining the omnipotent root. Sun shipped Solaris Zones in 2004, which its own engineers called chroot on steroids. Google needed to pack many jobs onto one machine without them fighting over memory, so Paul Menage and Rohit Seth wrote control groups, merged into Linux in 2008. Namespaces gave each process a private view of the system; cgroups capped what it could consume; together they became LXC, and the modern container was assembled from parts.
Every one of these is a way of saying you do not trust this process with the whole machine. You only ever bothered to build a box around code you had a reason to doubt: a tenant who was not you, a service exposed to the network, a job that might run away with the host’s memory.
And for thirty years the line moved the other way. You ran your own build scripts straight on your laptop, piped a stranger’s install script into a root shell with curl … | sudo bash and thought nothing of it, and let npm install run a package’s postinstall hook under your full user account on a tree of dependencies you had never read. The trend was toward trusting code more and isolating it less, because the code was yours, or close enough to yours, and the friction of a box was not worth paying. That was a choice, and for most of those years it was the right one.
The friendliest box wins
The box that won was not the strongest one. On March 15, 2013, Solomon Hykes gave a five-minute lightning talk at PyCon titled “The Future of Linux Containers.” He had expected a small side room and perhaps thirty people; PyCon ran its lightning talks on the main stage, so he demoed an unreleased tool called Docker to several hundred. Docker had grown out of dotCloud, a platform company that had built its internal infrastructure on LXC and found it unwieldy.
The critics were right about what Docker was. Under the hood it was LXC, namespaces, cgroups, and a layered filesystem, wrapped in a nicer interface. It invented almost none of the isolation. What it invented was the Dockerfile, the image you could push to a registry and someone else could pull and run, and docker run doing what you meant. It made a reproducible environment something you could describe in a dozen lines and hand to a stranger. It won on ergonomics, and it deserved to.
Docker took the leakiest mainstream isolation we had, a shared host kernel and a much weaker boundary than a VM’s, and made it the default way an entire industry shipped software. It did that by making the weak box so pleasant that nobody minded the weakness. For a decade that was a fine trade, because the thing in the box was still code you or your colleagues had written.
The leak we agreed to
The weakness is specific, and the whole argument turns on it. A virtual machine gives each guest its own kernel, so the boundary between guest and host is the processor’s virtualization hardware, a narrow and heavily scrutinized interface. A container shares the host’s kernel with every other container on the machine, so the boundary is the entire Linux system-call surface, more than three hundred calls, any one of which is a potential way through.
A container “escape” is a concrete event: a process that was supposed to be confined gets root on the machine that hosts it, and now it is loose on the host that holds every other container on that box, their environment variables, their tokens, the database credentials in the one running next door. None of that is hypothetical. In January 2024, researchers disclosed Leaky Vessels, a set of flaws including CVE-2024-21626 in runc, the low-level runtime underneath Docker and most of Kubernetes. It scored 8.6 on the CVSS scale, and the failure was the plain one, a full escape from the container onto the host.
When you wrote the code in the box, you could live with that risk, because you knew roughly what your code would try to do, the escape required a real exploit and an attacker who had already gotten in, and the odds were long. Put a hijacked agent in the same box and the math inverts, because the agent will try whatever the poisoned ticket tells it to try, enthusiastically, at three in the morning, with no one watching. The agent did not introduce the danger so much as remove the excuse you had leaned on for thirty years.
So AWS, Google, and others rebuilt the virtual machine, smaller. Amazon’s Firecracker, shipped in 2018, is about fifty thousand lines of Rust that boots a stripped-down VM in roughly 125 milliseconds, with none of the legacy hardware a normal VM emulates. It runs AWS Lambda and Fargate. Google’s gVisor takes a different route: a kernel written in Go that runs in user space and intercepts the workload’s system calls before they ever reach the host. Kata Containers wraps each container in its own lightweight VM outright. These are three shapes of one idea: shrink the boundary back down to something you can defend. The container had given away too much.
How the cage actually holds
The best working example of this is one you use every day: your browser.
Chrome’s security model assumes the renderer (the part that parses HTML, runs JavaScript, and decodes images, the part touching content from the open web) will be compromised, not as a possibility but as a working assumption. So the renderer runs as a separate, stripped-down process that can touch almost nothing directly. Every time it needs a file, a network connection, or anything from the operating system, it has to ask a second, privileged process, the browser or “broker,” which decides whether to allow it. The broker is what security people call a reference monitor: a single chokepoint that mediates every privileged action, small enough to get right. After Spectre, Chrome went further with Site Isolation, putting each site in its own process, because if a renderer can be made to leak its own memory then the only safe place for another site’s data is a different process entirely.
Underneath, on Linux, the cage is built from a handful of kernel parts that compose into a sandbox. None of them is sufficient alone.
Deep Dive: The primitives, one layer down
Namespaces give a process a private view of a global resource. A process in its own PID namespace sees its children and nothing else; in its own network namespace it has its own interfaces and routes; in its own mount namespace it sees its own filesystem tree. The process thinks it has the machine to itself.
cgroups (control groups) cap what a process can consume: CPU, memory, I/O, number of processes. This is not a security boundary on its own, but it stops a runaway or malicious workload from starving everything else, which is its own kind of attack.
seccomp-bpf installs a small program that the kernel runs on every single system call the process makes, deciding to allow, block, or kill. This is the main tool for shrinking that three-hundred-call attack surface down to the dozen or so a given workload actually needs. Chrome uses it as a second layer on its renderers.
Capabilities slice the old all-or-nothing root into roughly forty discrete privileges, so a process can bind a low port without also being able to load kernel modules. User namespaces map “root inside the box” to an unprivileged user outside it, so even if something believes it is root, the host disagrees.
All of this looks familiar across thirty years and three platforms because the design rules were written down in 1975. Jerome Saltzer and Michael Schroeder’s paper gave us least privilege, deny-by-default, and a trusted core kept small enough to verify; Apple’s Seatbelt enforces the same rules on macOS today. Assume the inside is hostile, and put a guard on every exit.
The occupant changed
Take Chrome’s one assumption, that the inside is hostile, and notice that the agent satisfies it perfectly, with one upgrade in the threat. A website you visit is hostile but contained to a tab, and it wants out; an agent is something you invited in and handed a shell, a filesystem, and a set of credentials, precisely so it could be useful. The renderer wants to escape its box, and the agent already lives in yours.
The agent cannot be patched out of this the way you patch a parser, because a browser parses untrusted input in order to process it without obeying it, while an agent’s entire job is to read input and obey it. The vulnerability and the feature are the same mechanism. You cannot ship the helpful version without shipping the exploitable one, so containment stops being a precaution you bolt on for risky workloads and becomes the runtime itself.
There is a symmetry in who is building this. Jeffrey Morgan and Michael Chiang, who built Kitematic, the graphical front end Docker bought and folded into Docker Desktop, left and made Ollama, which does for local language models what Docker did for containers, so that ollama pull and ollama run treat a model as an artifact you fetch and run with one command. The same instinct, friendliness laid over a hard piece of infrastructure, applied first to the box and now to the brain you put in it. Running the model locally also removes the party you would leak to, because if the weights and your prompts never leave the machine, there is nowhere to exfiltrate them.
The agent vendors admit it in their own documentation. Anthropic’s sandboxing for Claude Code stacks three layers (permission rules, a permission mode, and an OS-level sandbox built on Linux’s bubblewrap and macOS’s Seatbelt) so that the agent writes only inside its working directory and reaches the network only through a proxy that enforces an allowed-domain list. The stated payoff is that it cuts permission prompts by about 84%, because a sandbox nobody can stand gets switched off. The stated reason is one sentence, and it puts the whole argument into a product changelog:
It is a guilty plea entered in advance: we are going to be fooled, so build the box on that assumption.
The OS reorganizes around the box
Operating systems do not grow new primitives for fads.
At BUILD on June 2, 2026, Microsoft shipped MXC, Microsoft Execution Containers, an isolation layer for agents built into Windows and WSL. You declare what an agent may touch, which files and which network domains, and Windows enforces it at runtime, the way a phone gates an app’s access to your camera and contacts. It ships as a ladder of strengths. The bottom rung is process isolation, fast enough for an inner loop, and GitHub Copilot CLI already runs on it. Above that is session isolation, which cuts the agent off from your desktop, clipboard, and input. On the roadmap is a microVM tier, hardware-backed, for the high-risk jobs. Microsoft is climbing that ladder toward the VM.
Apple arrived at the same place from the opposite side. At WWDC 2025 it shipped Containerization and a container CLI that looks and feels like Docker, with one structural difference: each Linux container runs inside its own lightweight virtual machine, on the Virtualization framework Apple already had for Apple Silicon. This is not shared-kernel isolation with a VM bolted on for safety; it is a full VM per container, on by default, shipping in macOS 26.
Microsoft started at the process and is adding VM strength on top, while Apple started at the VM and gave it container ergonomics. Two of the largest platform owners on earth began from opposite ends and converged on the same primitive, the virtual machine we had in 1999, re-applied to the problem of code we cannot trust.
Everything in this story is a point in one tradeoff with three corners: how strong the isolation is, how cheaply and densely you can run it, and how much developers will tolerate using it. VMs took the first corner and gave up the other two. Containers took density and ergonomics and gave up isolation. Firecracker, Apple’s per-container VM, and Microsoft’s microVM tier are all the same move: buy back the isolation corner without surrendering the other two. And the move that makes it pay is throwing the box away. The agent’s sandbox is not cleaned between runs; it is destroyed and rebuilt. Its cheapness is its safety: a box that boots in 125 milliseconds is a box you can afford to kill the instant the work is done, before anything inside it persists.
Who holds the keys
Set the two cases side by side. You hand a stranger’s website a renderer you merely assume is compromised, and you trust the architecture to hold. Then you take the agent you chose, configured, and pay for, and you lock it in a virtual machine built for one task and destroyed before it can remember the last one. You trust the stranger’s code more than the thing you made, and you are right to, because you know which one will do what a poisoned ticket tells it to.
So the sandbox is not really protecting you from the agent; it is protecting you from a choice you keep making, because the useful version of this and the dangerous version are the same version. The box is what you build instead of trust, when trust is not available and the work has to happen anyway.
That leaves one question open. When the isolation primitive moves into the operating system, the policy moves with it. On Microsoft’s stack, the domains your agent may reach, the files it may touch, and the capabilities it may hold are set through Entra and Intune by whoever administers your tenant, not by you in a config file. Try to grant your own agent a capability the policy forbids and the command fails on the laptop you own, against a rule you cannot edit. That is good security. It is also a quiet relocation of control: you will run something you cannot fully read, in a box you did not design, under a policy someone else administers. You made the first move at 2am, when you handed it the keys.


