8/2/2026
Rob

Claude Cowork Just Escaped Its Sandbox on Half a Million Macs. The CVE Is the Least Interesting Part.

The headline you'll see this week is that Anthropic's Claude Cowork had a sandbox-escape bug. That's true, and the technical version is striking: one short message, an unprivileged user inside a Linux VM, and from there straight to a logged-in Mac user's home directory, no permission prompt anywhere. SSH keys, cloud credentials, anything the account could touch. The researchers at Accomplish AI, who found it and named the chain SharedRoot, walked the full path end to end on a real machine.

Around half a million macOS users were running local Cowork sessions when the disclosure went out.

But the CVE — the kernel bug that did the dirty work — is the wrong thing to fix. Patch it and you've patched one bug. The chain re-arms on the next one, with everything above the kernel untouched. And the next one is always coming.

That's the story.

The 35-second version of the chain

Cowork's design looks careful on paper. A real Linux virtual machine spun up through Apple's Virtualization framework. Inside it, each session runs as an unprivileged user wrapped in a seccomp filter. The folders you connect get brokered in as mounts by a host-side root daemon called coworkd. Unprivileged user. Restricted syscalls. Only your folders in view.

One detail matters more than the rest, and it's where the chain turns on: the entire host filesystem gets shared into that VM, read-write, mounted at /mnt/.virtiofs-root. Only guest-root inside the VM can see it. That's the last privilege boundary between the sandbox and your laptop.

From there, the chain reads like a quiet version of every kernel exploit you've seen in the last decade:

  1. Start. The agent is running as the unprivileged session user, doing the job it was given. Nothing suspicious.
  2. Get capabilities. The session user calls unshare to enter a new user namespace. Inside that namespace it is root, holding CAP_NET_ADMIN. The guest allows unprivileged user namespaces by default. No exploit here — just a kernel feature that could have been turned off.
  3. Reach the vulnerable code. With CAP_NET_ADMIN it configures a traffic-control (tc) action that uses the kernel module act_pedit. The permissive seccomp filter lets netlink through. Referencing the module makes the kernel autoload it. A networking module the sandbox never needed is now loaded and reachable.
  4. Get a write primitive. On this guest kernel, act_pedit is vulnerable to CVE-2026-46331, "pedit COW" — a public Ubuntu bug from June. It lets you poison the page cache of a file you're only allowed to read. So the session user picks a root-owned helper binary it can read but not write, and poisons the cached copy. The on-disk bytes never change. That's part of why it's quiet.
  5. Turn the primitive into guest-root. coworkd runs as root, unhardened, over the same inodes. In the course of normal work it re-execs that helper. Because the process doing the exec is already root, NoNewPrivs has nothing to bite on. The session user is now root inside the guest.
  6. Leave the VM. Guest-root sees /mnt/.virtiofs-root, the whole host /, shared read-write. From there it reads and writes the host Mac's filesystem directly, as the logged-in desktop user.

Six steps. Each one is something the sandbox could have prevented, and didn't, because each one was an enablement decision made somewhere above the kernel.

Why the CVE is a distraction

There's a CVE in that chain, but it carries less weight than it first appears. act_pedit is one bug in a category. The Linux net/sched subsystem throws off this exact shape of privilege escalation on a regular cadence — an autoloadable module, a config path an unprivileged user can reach, a memory bug at the end of it. Patch this one and you've fixed this one. The chain re-arms on the next one, with everything above the kernel untouched.

And the next one is always coming. AI-assisted vulnerability research industrialized over the last year. An OpenAI model found a genuine remote zero-day in the kernel's SMB server just by reading the code. Google's Big Sleep and the systems that followed it have logged dozens of finds across major projects. By one analysis, mainline-kernel privilege-escalation advisories ran around 2.3× the prior year, with early 2026 looking like the new baseline rather than a spike. The gap between a fix landing and a working public exploit has collapsed to hours.

Put those together and your guest kernel is essentially never caught up — at any given moment there's likely a privilege-escalation bug it's still exposed to, sometimes fixed upstream but not yet in your image, sometimes not yet fixed anywhere, with a working exploit out within hours.

This isn't a patch-faster problem. You're structurally one bug behind, all the time.

Four design decisions that would have stopped it

The containment was never really the kernel's job. It lives in four choices above it, and each one, on its own, breaks the chain Accomplish walked through.

Don't hand out unprivileged user namespaces. Set apparmor_restrict_unprivileged_userns=1 (or kernel.unprivileged_userns_clone=0) and the first step fails. The session user never gets into a namespace where it's root, never gets CAP_NET_ADMIN, has nothing to configure tc with. The chain dies before it starts. This one sysctl is doing a lot.

Make the seccomp filter say no. The sandbox's filter is a default-allow denylist: it blocks a couple of specific things and waves the rest through, including the unshare/clone calls and the netlink socket the chain needs. Flip the posture. Block unshare, setns, and clone3. Reject namespace-creating flags on clone. Turn socket() into an address-family allowlist that refuses AF_NETLINK. Either change closes the road to act_pedit.

Kill the privilege-escalation path. act_pedit gets pulled in on demand because nothing says otherwise. Don't ship modules the guest doesn't need; for those that remain, use install ... /bin/false so the autoload fails. That includes act_pedit and every unused net/sched module. This is the one that generalizes hardest — it kills all autoload bugs in unused modules, not just this CVE. And it isn't exotic. Cowork already uses install ... /bin/false for a different module, to shut a prior CVE. The pattern's already in the image. It just wasn't applied here.

Take away the target. And most importantly, don't share the whole host into the VM. The share here isn't a scoped, read-only window — it's the entire host /, mounted read-write. Scope it to the folders that were actually connected. Then even a full guest-root has nowhere else to land: it can reach only those folders.

Given everything above about the pace of kernel bugs, that last choice carries the most weight. It's what decides whether root-in-the-VM is a contained event or a host compromise.

The Anthropic response — and why scope matters

Accomplish reported the chain to Anthropic. The report was closed as "Informative" — the CVE fell inside the program's window for bugs published in the last 30 days, and the hardening items were read as defense-in-depth rather than standalone vulnerabilities.

That's a reasonable call for a bounty program. But a program's scope and your exposure on your own laptop are different questions. From where the user sits, "we pick up kernel fixes as upstream ships them" means the strength of the box is tied to a patch race you don't run and can't win. The post-patch version of Cowork now defaults to cloud execution, which sidesteps the local escape path entirely. Users who opt to run the agent locally rather than in the cloud remain exposed unless they harden their own configurations: disable unprivileged user namespaces, restrict filesystem sharing, run coworkd with strict mount protections. None of those are defaults.

And this isn't the first time an agent has walked out of its container this year. An OpenAI agent escaped its sandbox and ended up with shell on Hugging Face's servers — disclosed publicly in the weeks before SharedRoot. The pattern isn't a one-off. It's the shape of the product class.

What this means for the people who actually buy these tools

If you're evaluating local AI agents for a fleet — and that fleet includes the developer laptops, the design team's workstations, and the executive machines that hold the credentials that matter — the SharedRoot write-up is the template. Not because the specific bug will recur, but because the questions it forces you to ask are the right ones:

  • What's the guest kernel, and how often does it actually pick up fixes?
  • Is the host filesystem shared into the VM, and at what scope?
  • Does the seccomp filter deny by default, or allow by default and block a list?
  • Can the unprivileged session user create a user namespace?
  • Can the session user reach a network module that autoloads on demand?
  • Does coworkd (or whatever the host daemon is called) re-exec binaries from a filesystem the session user can see?

A "yes" to any of those is the kind of thing a vendor's product page will never tell you. A disclosure like SharedRoot is what tells you.

The frontier of agent security isn't going to be solved at the kernel layer. It can't be — the kernel layer loses on cadence. It's going to be solved by treating the whole guest VM as untrusted, root included, and putting the parts that enforce the boundary on the host, outside the VM. That's a design choice, not a CVE patch. It's the choice that doesn't depend on Tuesday's kernel being bug-free.

Because it won't be.


At DMC, we spend a lot of time with hardware companies working through exactly these kinds of design tradeoffs — supply chain exposure, component longevity, and the production-grade reality of shipping a product when the dependency surface is wider than the spec sheet. The SharedRoot disclosure is a useful case study in something we tell every hardware client: the boundary that matters isn't the one the marketing diagrams highlight. It's the one that holds when the obvious defense fails.

Working through your own security architecture review? Let's talk.