macOS: session processes are denied Local Network access despite the grant (bundle_id: (null) at evaluation)
Summary
On macOS, every process spawned by a Claude Code session inside the Claude desktop app is denied
Local Network access, even though /Applications/Claude.app has been granted it in System
Settings. connect() to any address on a directly-attached subnet returns EHOSTUNREACH
immediately; the tailnet and the public internet are unaffected, so it presents as a routing fault
rather than a permissions one.
The cause appears to be attribution: the responsible process is the versioned helper bundle~/Library/Application Support/Claude/claude-code/<version>/claude.app/Contents/MacOS/claude,
which is correctly signed as com.anthropic.claude-code, but macOS evaluates the connection withbundle_id: (null) — so the grant recorded against com.anthropic.claudefordesktop cannot
apply, and the default is deny.
Environment
- macOS 27.0 (26A428), Apple silicon
- Claude desktop 2.2553.1
- Claude Code helper 2.1.275 (2.1.271 also present on disk)
Evidence
At the moment of each blocked connect, with an ordinary Python socket to a host on the local
subnet:
UserEventAgent[357] [com.apple.networkextension:] Got local network blocked notification:
pid: 2194, uuid: 4C4C4493-…, bundle_id: (null)
kernel: tcp drop outgoing [<IPv4-redacted>:51822<-><IPv4-redacted>:2222] interface: en0
process: Python:2999 t_state: SYN_SENT so_error: 0 reason: NECP
pid 2194 is the session's parent:
2194 2190 …/Claude/claude-code/2.1.275/claude.app/Contents/MacOS/claude …
2190 2022 /Applications/Claude.app/Contents/Helpers/disclaimer
2022 1 /Applications/Claude.app/Contents/MacOS/Claude
and that bundle is properly identified and signed:
$ codesign -dv …/claude-code/2.1.275/claude.app
Identifier=com.anthropic.claude-code
TeamIdentifier=Q6L2SF6YDW
$ plutil -p …/Contents/Info.plist | grep CFBundleIdentifier
"CFBundleIdentifier" => "com.anthropic.claude-code"
The only Local Network client recorded for Anthropic is the desktop app:
$ sudo plutil -convert xml1 -o - /var/db/locationd/clients.plist | …
com.anthropic.claudefordesktop | /Applications/Claude.app | registered: True
The control that isolates it
Same machine, same user, same binary, same second — once via launchctl submit, once from the
session's own shell:
| target | launchd-spawned | Claude Code session |
|---|---|---|
| gateway :443 | OPEN | EHOSTUNREACH |
| LAN host :2222 | OPEN | EHOSTUNREACH |
| LAN host :5000 | OPEN | EHOSTUNREACH |
| LAN host :22 | OPEN | EHOSTUNREACH |
The LAN is healthy throughout — other applications hold dozens of established TCP connections to
those same hosts while the session cannot open one.
Reproduction
- Run Claude Code inside the Claude desktop app on macOS 15+.
- Grant
/Applications/Claude.appLocal Network access in System Settings → Privacy & Security. - From the session, connect to anything on your own subnet:
python3 -c "import socket;s=socket.socket();print(s.connect_ex(('192.168.x.y',443)))"
- Result:
65(EHOSTUNREACH), instantly. The same command from alaunchctl submitjob on the
same machine returns 0.
What does not fix it
- Granting
/Applications/Claude.appLocal Network access (already granted,registered: True). - Quitting and reopening the desktop app.
- Toggling the generic
claude.appentry in the Local Network list off and on. dangerouslyDisableSandboxon the Bash tool, so it is not Claude Code's own sandbox.- Trying a different interpreter — Apple's
/usr/bin/python3, Homebrew'spython3.12, and
/usr/bin/curl all fail identically, so it is the process tree and not one binary's grant.
The single exception is a configured DNS resolver on the LAN, which connects because macOS exempts
those from the local-network rule.
Impact
Any workflow where Claude Code has to reach the machine's own network is silently impossible:
home-lab and on-prem hosts, printers, local databases and dev servers on another machine, private
registries, and DNS to a LAN resolver. Because lookups to LAN nameservers fail too, name resolution
breaks in ways that look unrelated — in this case a public resolver had to be added to the Mac's
DNS list before the session could resolve anything at all.
It is also very hard to recognise: the error is EHOSTUNREACH with a valid route and a populated
ARP entry, which is indistinguishable from a dead network unless you happen to compare against
another process on the same host.
Suggestion
Whatever establishes the responsible-process attribution for the session's children should resolve
to a bundle identifier, so that a grant made against the app actually covers them — either by
having the helper inherit com.anthropic.claudefordesktop, or by registeringcom.anthropic.claude-code as its own Local Network client that the user can grant once and that
survives a version bump (the bundle path contains the version, so any per-path grant goes stale on
every update).
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗