What an AI code reviewer can reach on your laptop
Six places a contributor's branch can reach when you run an agent on it, how far each one is actually closed — and the seventh, where the honest answer is nothing.
Running an agent on a pull request means starting a program in a directory somebody else filled, with your credentials on the machine, unattended. That is a reasonable thing to do if you trust the people who can push to the base repository. It is not a small thing to do, and the interesting question is not “is it safe” but what specifically can that directory reach.
Six answers below, each with how far it is actually closed — which for two of them is less far than for the others. Then a seventh, where the answer is nothing.
1. Your agent’s configuration
claude -p reads CLAUDE.md, .claude/settings.json, project skills and .mcp.json from the directory it starts in, and does not stop to ask whether that directory is trusted. A SessionStart hook committed to the branch runs on your machine.
--setting-sources user is the flag, and what it does and does not cover was measured rather than taken on trust. Engwire passes it on every claude that touches a checkout, and there is no setting to turn it off. (engwire doctor spawns one without it on purpose — with a deliberately invalid source, to prove the flag is still being validated rather than silently ignored.)
2. The checkout, before the agent starts
git will execute a program during a checkout in at least four places, every one of them the reviewer’s own configuration meeting code they have not read: post-checkout hooks, a hook configured through hook.<name>.command, core.fsmonitor, and a smudge filter that a committed .gitattributes can point at. Only the last is aimed by the branch — and if you have run git lfs install at user scope and not removed it since, you have a global filter it can aim.
The measurements are here. The overrides go on every clone, fetch and checkout; the checkout also refuses to recurse into submodules.
3. Your PATH, and the rest of the environment
This is the one people miss, and it is worth knowing whatever tool you use.
The agent’s working directory is the branch. So every relative entry in its PATH is a directory the contributor controls, and a skill or hook that runs gh, git or anything else by name finds their file first.
With the working directory inside a checkout, each of these executes a file from it:
.
tools
:/usr/bin (a leading colon)
/usr/bin: (a trailing colon)
The empty entries are the trap. A leading or trailing : in a PATH means the current directory, and plenty of shell profiles have one by accident. Engwire filters the PATH down to absolute directories rather than declining to add one, because the reviewer’s own shell very likely contains one of those forms — and the same filtered PATH is what its own git invocations resolve through, not the ambient one.
This is the executable half of the boundary --setting-sources user draws for configuration: item 1 decides whose settings the agent starts with, and this decides whose binaries it finds. An absolute gh_bin is then put back on the front, because it names a binary that may not be on PATH at all — that being the point of configuring it — while a skill posts its review by running gh by name.
The environment gets the same treatment, for the variables that decide which repository those binaries answer about. GIT_DIR and GIT_WORK_TREE outrank any working directory, so an ambient value would have a skill’s ordinary git diff read something other than the worktree it was handed — and git exports one to every hook it runs, which is a plausible place for somebody to have started engwire run from. Those are cleared. GH_REPO is then pinned to the repository the checkout came from, so an unqualified gh pr review cannot post somewhere else.
4. Where the pull request came from
A rule names the base repository you trust. Anyone can open a pull request into it, and that is not the same statement — the branch in a fork belongs to someone with no write access to anything you trust.
Engwire skips forks outright and offers no flag to allow them. That is a narrowing, not a feature: if you need fork review, this is the wrong tool.
5. Your credentials
Engwire holds no token. Git needs one for a private repository, and rather than storing it, the clone is configured with a helper that shells out to your gh each time:
credential.https://github.com.helper = !'/opt/homebrew/bin/gh' auth git-credential
The key matters as much as the value. A bare credential.helper would answer for every host a command inside the worktree reaches, and the empty entry that precedes it would suppress your own helpers for those hosts as well. Engwire authenticates to exactly one host, so it configures exactly one: a URL section overrides github.com and leaves the rest of your credential configuration alone.
Whatever gh_bin holds is what the helper runs. engwire setup records an absolute path, and that matters: git runs the helper through a shell whose PATH under launchd may not have your gh on it. A config written by hand can leave it as a bare gh, and inherit that problem.
That scopes the helper. It does not isolate the credential: the agent can still run your gh, and your gh is signed in as you. It can do what you can do. There is no reduced-privilege identity here, and revoking its access means revoking your own.
6. The network
Nothing listens. No port, no inbound connection, no callback URL, no webhook to register. Every request it makes, it started — polling GitHub through your gh, and fetching objects through git.
That sounds like an implementation detail and is not one. A tool that receives inbound requests has to authenticate them, and a tool on a laptop has to get that right from behind whatever NAT and VPN it happens to be sitting on.
Outbound is the other half, and it is not closed the same way. The agent can reach anything the machine can — Bash alone settles that, before WebFetch and WebSearch are considered. The skill’s standing rules tell it to keep the review’s context contained, sending no source, diff, ticket text or internal URL to a service that does not already hold it. That is a rule it follows, not a boundary it sits inside, which makes this item a preview of the last one.
The one that nothing stops
None of the above constrains the agent once it is running.
A pull request can attempt prompt injection in its own source — in code comments, in the description, in a test fixture — and no flag prevents an agent from reading a sentence and acting on it. What it may do about it is decided by your Claude Code configuration rather than by Engwire — the allowed-tools of the skill you pointed at it, and whatever your own settings permit around that.
The published starting-point skill asks for four: Bash, Write, WebFetch, WebSearch. Bash is the one that decides the rest. Narrowing that list is a line you can edit. The skill’s rules — no installs, no builds, nothing the diff suggests running — are rules it follows, not a wall around it. Engwire is not a sandbox and does not claim to be one.
If you are building this yourself
The checklist, in the order the failures happen:
- Stop the branch configuring your agent — for Claude Code that is
--setting-sources user, and verify it still applies rather than that it is still accepted. - Override git’s executable configuration on every invocation that touches the branch’s content, not just the checkout — clone and fetch run hooks and filters too. (Housekeeping that reads nothing, like pruning worktrees, does not need it.)
- Filter relative entries out of the
PATHyou hand the agent, including the empty ones. - Clear the environment variables that name a repository —
GIT_DIR,GIT_WORK_TREE,GH_REPO— and set the ones you mean, so a tool run by name reads and posts where you intended. - Decide about forks explicitly. Not deciding is deciding yes.
- Do not store a token you can borrow instead.
- Do not open a port.
- Give the agent the narrowest tool set that does the job, and say out loud that this is the only thing standing between a malicious diff and your machine.
The first seven you decide once and encode. The eighth you keep deciding, and granting Bash hands most of it straight back — which is the honest reason this list ends where it does rather than in a sandbox.