DEV Community

Deland
Deland

Posted on AI-assisted

Four ways to sandbox a coding agent on a Mac, and where each one leaks

Disclosure up front: I build Kyvenza, a paid VM manager for Apple Silicon, and it comes up near the end. Most of this post applies to any VM tool, and one section is about where mine is the wrong choice.

Coding agents with shell access are useful for exactly the reason they are risky: they run commands as you. The permission prompts get tiresome, everyone eventually switches them off, and from then on the only thing between a confidently wrong command and your SSH keys is the quality of the model's day.

So the real question is not "how do I make the agent careful". It is "what can this process reach if it is not". Here are the four places I have seen people put an agent on a Mac, and what each one still lets through.

1. The same user account

This is the default, and it is no isolation at all. The agent inherits your Keychain access, ~/.ssh, browser profiles, cloud CLI credentials, and every file you can read. A single prompt injection in a README the agent fetches has the reach you have.

Nothing leaks here because nothing is held back.

2. A second macOS user

A standard second account is a real improvement. macOS home folders are not readable by other standard users, and the agent's Keychain is its own. For accidents, this works.

What survives:

  • Anything listening on localhost. A dev server or database bound to 127.0.0.1 is reachable by every user on the machine. If your real work has a local database with real data, the second user can open a socket to it.
  • World-readable locations, such as /Users/Shared and anything under /tmp you forgot about.
  • Admin rights. The moment the agent is allowed sudo, which many setups grant to avoid more prompts, the separation is a suggestion.

It is the same kernel and the same operating system. It protects you from the agent's mistakes more than from its compromise.

3. A container

On a Mac, containers are not native. Docker Desktop and similar tools run a Linux virtual machine and start your containers inside it, sharing that VM's kernel. For headless Linux tooling this is excellent: fast to create, easy to throw away, reproducible.

What survives is mostly configuration:

  • Mounted folders. -v ~/code:/work gives the agent read and write access to everything in ~/code, including the .env files you did not think about.
  • The Docker socket. Mounting docker.sock into a container is a well-known way to hand it control of the Docker engine, and through it, any other container and mount.
  • Network. The default bridge can reach whatever your Mac can reach, including internal hosts on a VPN.

And there is a scope limit: a Linux container cannot run macOS software, so it is the wrong tool if the agent needs to build an app, drive a GUI, or test on Windows.

4. A virtual machine

A VM gives the agent its own operating system, and the boundary is enforced by the hypervisor rather than by permissions you configured. Nothing on your host is visible unless you share it. It also gives you the one thing the other three do poorly: you can roll the entire machine back to a snapshot taken before the agent started.

Two properties turned out to matter more in practice than raw isolation:

  • A disposable clone. On APFS a copy-on-write clone of a prepared VM appears in about a second and costs almost nothing on disk until the guest writes to it. That makes "run it in a throwaway copy" cheap enough to be the default.
  • A network switch you can turn off. A VM can be given no network adapter at all. The question becomes how the agent still does anything useful, which is where a command channel that is not the network matters (more below).

What a VM still does not fix

This is the part I would want to read if I were deciding.

  • Shared folders are a hole you dig yourself. If you share your home directory into the guest to make life easier, you have rebuilt option 1 with extra steps.
  • The guest can still talk to your host. With QEMU-style user-mode networking, anything the guest sends to 10.0.2.2 is translated into a connection to the host's loopback interface. A running Windows guest can therefore reach services bound to 127.0.0.1 on your Mac. This is why any local control server, including the one Kyvenza ships, needs an authentication token and not just "only listens on localhost".
  • Credentials you paste in are credentials the agent has. A fresh VM with your real GitHub token is only as safe as that token's scope. Give it credentials that work on throwaway repos.
  • Escapes exist. Hypervisor vulnerabilities are rare but real. Keep macOS updated, and use a no-network guest for code you actually distrust.

The workflow that stuck

What I settled on, whichever VM tool you use:

  1. Build a clean base VM once: the OS, the toolchain, nothing personal. Shut it down and treat it as read-only.
  2. For each task, clone it. Never run the agent in the base.
  3. Let the agent run in the clone. For untrusted installers, set the clone to no network.
  4. Read the result, then delete the clone.

For the agent to do this itself rather than me clicking through it, the VM manager needs to be drivable. Kyvenza has a local MCP server (off until you enable it; loopback only; one token per Mac) with fifteen tools: start, stop, snapshot, restore, run a command in the guest, take a screenshot, and clone. The tools that create, clone or delete VMs are hidden from the agent until you switch them on, delete_vm only deletes clones it made and sends them to the Trash, and starting a VM through MCP takes a snapshot first. With Claude Code the connection is one command:

claude mcp add --transport http kyvenza http://127.0.0.1:59800/mcp/YOUR-TOKEN
Enter fullscreen mode Exit fullscreen mode

On a Linux guest with the guest agent installed, commands and screenshots go over a virtual socket, so they keep working with networking switched off. That is the combination I wanted: an agent that can work, and code that cannot phone home.

Where this is the wrong tool

  • If a container is enough, use a container. Headless Linux tooling, CI-style tasks and anything that does not need a desktop are quicker and lighter in Docker. A VM is more weight than that deserves.
  • Windows with graphics. Kyvenza runs Windows 11 on ARM without 3D acceleration, USB passthrough or microphone input. For anything graphical on Windows, Parallels is the better product.
  • It is not free. There is a 7-day trial, then it is $49 once. VMware Fusion Pro and UTM are free and cover the VM part of this post, though without the built-in MCP server.
  • Intel guests. Apple Silicon virtualizes ARM guests only. No x86.

Takeaway

Pick the weakest boundary that matches what the agent can break. A second user for low-stakes work, a container for headless Linux, a VM when the agent needs a desktop, runs untrusted code, or can touch things you cannot afford to lose. Then fix the leaks that survive in all of them: shared folders, scoped credentials, and the network.

I wrote a longer, vendor-neutral version of the comparison table here: Run an AI agent safely on a Mac, and the full MCP tool list and limits are on the MCP page.

Top comments (0)