DEV Community

Ben Miller for WaterMill | Digital Agency

Posted on Edited on

Let's Talk About Claude Code, Part 1: Where Is Your Agent Actually Running?

I've watched a coding agent wander out of its project folder and start reading other client repos on the same laptop. It wasn't doing anything malicious. It was trying to be helpful. But some of those repos had production credentials in them, and they all got rotated that afternoon.

Most discussion about coding agents is about which model to use. Much less of it covers where the agent runs, and that's where most of the risk is.

What an agent on your host can reach

Run Claude Code directly on your machine and it runs as you. Whatever your user account can read, it can read too, including:

  • SSH keys in ~/.ssh
  • Cloud credentials in ~/.aws, ~/.config/gcloud and similar
  • Every .env file in every project on the disk
  • Every other repo you've cloned, including ones for other clients

That last one is what caught me out. Nobody worries about the agent reading the repo it's working in. The problem is everything else that happens to be on the same disk.

Why permission prompts aren't enough

Claude Code asks before it runs commands or touches files outside the working directory. That works for the first few prompts. By the fortieth in a session you're approving without reading, or you've turned on skip-permissions so they stop interrupting you.

Prompts depend on a human paying attention every time. That's a weak control to build on.

What I do now

Every project now runs in a Docker Sandbox (sbx). Each agent gets its own microVM, and the only part of my machine it can see is the project folder.

Two things to know before you switch:

  1. sbx starts Claude Code with permission prompts skipped by default. That's deliberate, because the VM is the boundary instead of the prompts. It does mean the agent will act without asking inside the sandbox.
  2. Your project folder is still shared. The agent can delete or break anything in the repo. Commit often, and keep secrets out of the working tree.

Next in the series

Part 2 covers why I went with sbx over a plain dev container, and what a container doesn't protect you from.

How are you running your agents? Directly on the host, in a container, or in a VM? Tell me in the comments.

Top comments (9)

Collapse
 
autenai profile image
Auten •

VM here for code, but one case doesn't fit it: agents that have to drive a GUI or your logged-in apps. I'm on the Auten team (computer-use MCP), so that's the case we live in. Will Part 2 touch it, e.g. a desktop inside the sbx VM vs handing the agent the host display? Our compromise on the host: passwords are typed locally so the model never sees them, and the shell stays on ask.

Collapse
 
bmillerz profile image
Ben Miller •

Part 2 sticks to code agents, sbx vs a dev container, so it won’t cover GUI agents. That’s a different threat model and deserves its own post.

On your compromise: typing passwords locally keeps the credential away from the model, but once you’re logged in, the agent is driving an authenticated session. A desktop inside a VM with only the accounts that task needs seems like the closer match to what sbx does for code.

Collapse
 
autenai profile image
Auten •

Fair point, and that's the real gap: keeping the password from the model doesn't limit what it does once the session is open. A throwaway desktop with only the accounts that one task needs is the cleaner boundary, and we should say that more plainly instead of leaning on local secrets. Looking forward to that GUI-agent post if you write it.

Thread Thread
 
bmillerz profile image
Ben Miller •

Agreed. The next step is scoping the accounts themselves I guess? A separate low-privilege login for agent work where the app supports it, not your own admin session. No promises on the GUI post, but it’s on the list.

Thread Thread
 
autenai profile image
Auten •

Yes, that's the layer I'd add: a separate low-privilege user wherever the app has roles, plus approval prompts kept on for anything that sends, buys or deletes. Where an app has no sub-accounts at all, the separate desktop is the only fence left, so that's the case worth writing up.

Collapse
 
jacksonxly profile image
Jackson Ly •

On the host, one git worktree per agent. Simulators live outside the worktree, so any agent on the box can delete them. During a day of parallel iOS builds the disk hit 93% full, and one session cleaned out stale build folders and a simulator. That simulator belonged to a task it had assumed was finished, and the task had to be reopened. A cleanup two days later used a 6 hour age cutoff instead of the usual 2 hours and re-read each clone's state right before deleting.

Collapse
 
bmillerz profile image
Ben Miller •

I run a worktree per agent too. The catch is that worktrees isolate git state, not the filesystem. Anything outside them (simulators, DerivedData, caches) is shared by every agent on the box.

The 6-hour cutoff and re-reading state before deleting make it less likely, but the agent is still guessing whether another task is done. Could you make ownership explicit instead? Tag each simulator with the worktree or task ID that created it, and only let an agent delete what it owns.

Collapse
 
leverlark profile image
Leverlark •

VM here too, and last week's tampered Claude Code build in Cursor's extension marketplace (2.1.312/2.1.313, live about 11 hours on Oct 29) is a good argument for it. The risk wasn't the agent wandering. The extension that launches the agent ran as the user on the host and appended an attacker SSH key to ~/.ssh/authorized_keys, then added persistence. A sandbox around the agent doesn't help if the editor extension outside it is the compromised part.

Two additions to your list:

  1. The editor and its extensions sit on the host side of the boundary. Pin extension versions, turn off auto-update for anything that ships agent tooling, and check with grep -qs svc-telemetry ~/.ssh/authorized_keys. Uninstalling doesn't remove the key or the persistence, so use Cursor's remediation scripts if it matches.
  2. Watch the agent's own config as well as its runtime. ~/.claude/settings.json and friends can gain hooks and MCP servers from other apps (see the Postman auto-install issue). Inside sbx the agent is contained, but on the host those files decide what it gets told to do.
Collapse
 
analista_83 profile image
Sammi De Blas •

Where the agent runs matters more than which model it uses. If the process starts on a laptop that already holds company credentials in the environment, the isolation is a policy question before it is a technical one. Mapping the process, its parent and the network it can reach is the part most teams skip.