[BUG] CLI binary spawns subprocesses (e.g. gh) outside the permission model — invisible to allowlist audits
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
The Claude Code CLI binary executes external commands on the user's machine that are not routed through the Bash tool, not subject to permissions.allow / permissions.deny, and not surfaced in the permission UI. The PR-status polling that calls gh pr view --json … (#37583, #23580) is one example. There is no documented inventory of which subprocesses the binary may spawn on its own behalf, no permission surface that can opt out of them as a class, and no audit log to review.
This contradicts the documented permission model: file reads, file writes, Bash commands, MCP tools, and the WebFetch domain check are all gated by allowlist entries the user can inspect. A user auditing permissions.allow has no signal that any other process can be launched by the binary.
The specific gh polling has a per-feature workaround (prStatusFooterEnabled: false in ~/.claude.json), but per-feature opt-outs do not address the principle. Any future feature spawning git, kubectl, docker, op, or any other tool would ship with the same invisibility unless the design changes.
What Should Happen?
In increasing order of effort:
- Document the inventory. A docs page enumerating every external command the CLI may spawn outside the Bash tool surface, with trigger, cadence, data sent, and disable mechanism per command.
- Surface them in
permissions.allowas synthetic entries (e.g.Internal(gh:pr-status)) following the same allow/deny/ask semantics as everything else. - A single global toggle (e.g.
internalSubprocessesEnabled: false) for users opting out of the entire class.
(2) is the closest fit with the existing permission model.
Error Messages/Logs
# execsnoop-bpfcc capture demonstrating spawn-from-claude:
PCOMM PID PPID RET ARGS
gh 2591263 2515429 0 /usr/bin/gh pr view --json number,url,reviewDecision,isDraft,headRefName,state
gh 2591620 2591425 0 /usr/bin/gh auth token
$ ps -p 2515429 -o pid,ppid,comm,args
PID PPID COMMAND COMMAND
2515429 1891746 claude claude
permissions.allow at the time of capture: zero gh-related entries.
Steps to Reproduce
- Examine
~/.claude/settings.jsonand project / local — confirm no entries authorizing the binary to invokegh - Open Claude Code on a branch with an open PR
- In another shell:
sudo execsnoop-bpfcc -n gh - Observe
ghinvocations whose PPID resolves to theclaudeprocess - Confirm: no permission prompt, no entry in
permissions.allow, no documented authorization
Claude Model
Opus
Is this a regression?
I don't know
Claude Code Version
2.1.119 (Claude Code)
Platform
Anthropic API
Operating System
Ubuntu/Debian Linux
Terminal/Shell
Other
Additional Information
Terminal: ddterm (GNOME shell extension) running zsh on Ubuntu 24.04.4.
- Related: #37583 (gh polling resource impact, has the
prStatusFooterEnabledworkaround), #23580 (closed stale; original reverse-engineering). The broader pattern of permission-bypass issues #16180 / #50046 / #50303 / #51902 covers user-invoked Tool calls escaping enforcement; this issue is the inverse — binary-invoked subprocesses that never enter the Tool layer. prUrlTemplateandprStatusFooterEnabledalready accept that this surface needs configuration. The request is to generalize that to any internal subprocess.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗