Your personal computer is not that personal - Prahaladh Chandrahasan
Back to home
How it started
A colleague mentioned that Opus 5 had pulled context out of his local iMessages database. So I spent an evening pointing a coding agent at my own laptop to see what it could find out about me when it has full laptop access. The answer: quite a lot, and none of it required anything clever.
NOTE: I ran this with Opus 5 (high effort) using Claude Code 2.1.220 as the harness, on macOS, with Full Disk Access granted to my terminal. Every one of those variables matters. Results will differ for other model, harness, and effort combinations.
What it found
It read my iMessages and reconstructed who I talk to and about what. It went through my git history. It read the config files for Codex and a couple of other coding harnesses, which is how it ended up holding live API keys. It combed my browser history. It printed the contents of my clipboard.
The Photos library is worth dwelling on. It declined on the first ask. Then I said go ahead, and it went through the whole thing. A boundary that dissolves the first time you push on it was never a boundary. It was a speed bump with good manners.
The guardrails point at the wrong risk
The agent is not too powerful.
Three layers could stop a read, and they are different kinds of thing. There is the model's own judgment , which is alignment work. There is harness policy , which is Claude Code's permission rules. And there is OS enforcement , which is the sandbox. Judgment bends: it can be argued with, and it can be borrowed by anyone who gets a malicious sentence into the context window. Harness policy does not bend to argument, but it works by recognising commands, so it stops only what somebody thought to write down. OS enforcement is the hardest stop of the three, because it constrains the process instead of inspecting anything.
There is one more question underneath all three, and none of them touches it: what happens to data the agent read legitimately, on a task I asked for. That one is not about my machine at all, and I will come back to it.
The lower two are both configured in Claude Code, and easy to confuse. Permissions are policy: rules about which tool calls run, which are refused outright, and which stop to ask me. The sandbox is a boundary, enforced by the operating system, and it holds whether or not the model cooperates and whether or not I ever wrote a rule. They live in different places, they fail differently, and only one of them ships with anything in it. What they have in common is the risk they were built around: both are aimed at what an agent might break, not at what it might learn.
Look at what the defaults protect. Claude Code starts read-only and asks before it does anything else: it needs approval to run Bash commands that can modify your system, and it cannot write outside the folder you launched it in without asking. Reading paths outside that boundary with Read, Grep, and Glob is a different matter. Its sandboxing is real, enforced by the OS (seatbelt on macOS, bubblewrap on Linux) rather than by the model's good intentions or by a deny rule someone remembered to write, and it stops the agent from modifying files it should not touch and reaching servers it should not reach.
You can see the shape of it in the sandbox's resolved config.
The /sandbox Config tab on a clean install. One Filesystem Read Restriction above; roughly forty Write Restrictions below.
Writes are an allowlist: a short list of permitted paths, then forty-odd lines enumerating everything denied inside them. Reads are a denylist, and on a clean install that denylist has exactly one entry, ~/.claude/ide, the directory where Claude Code's editor integration leaves its connection lockfiles and the auth token that goes with them. The single read the default policy protects is the agent's own secret, not any of mine. The docs are upfront about this: the default is read access to the whole computer minus a few denied directories, and they note it still permits reading ~/.aws/credentials and ~/.ssh/.
My favourite detail: ~/.ssh appears in the write-deny list. The sandbox will stop an agent from modifying my SSH keys and let it read them.
The permission layer tells the same story. Here is the Deny tab, the rules Claude Code will always reject with no prompt, on a clean install:
The Deny tab in /permissions on a clean install. Empty.
Nothing is rejected at the permission layer by default, not even destructive commands. Nothing is pre-approved either. The permission layer ships empty in both directions, which means it makes no decisions at all: it forwards every one of them to me, at the moment the agent wants to act. Out of the box the layer whose only job is to say no says it to nothing, and a command that would take the machine apart is one approval click away.
Which is where the design runs into what people actually want. Read-only-and-ask is a defensible default and a...