Claude Desktop update breaks LAN SSH/network access (OPERON_SANDBOXED_NETWORK=1)

Status Closed — not planned
Maintainer reply None cached
Activity 14 comments · opened Mar 23, 2026 · closed Aug 22, 2026

Description

After a Claude Desktop update (March 23, 2026), all local network access from Claude Code running inside Claude Desktop is blocked. SSH, SCP, ping, curl to LAN hosts all fail with "No route to host". This was working fine before the update.

Environment

  • Claude Desktop on macOS (Darwin 25.3.0, Apple Silicon)
  • Claude Code running inside Claude Desktop (CLAUDE_CODE_ENTRYPOINT=claude-desktop)
  • LAN subnet: 192.168.10.x
  • Local IP: 192.168.10.62 (en0, correct subnet)
  • Target host: 192.168.10.216 (Mac Mini on same subnet)

Symptoms

  • ping 192.168.10.216 → "No route to host"
  • ssh hosmera@192.168.10.216 → "No route to host"
  • curl http://192.168.10.216:5050/ → connection refused
  • nc -z 192.168.10.216 22 → fails
  • Same commands from a regular terminal work fine
  • ARP entry exists and is valid
  • Route table is correct (route get shows proper interface)

Root cause

New environment variable OPERON_SANDBOXED_NETWORK=1 is set in Claude Code's process environment when launched from Claude Desktop. This was not present before the update. Unsetting it in the shell doesn't help — the restriction appears to be enforced at the macOS sandbox profile level.

Impact

This breaks any workflow that involves deploying code to local servers, SSHing into local machines, or interacting with LAN services. In our case, we use SSH/SCP to deploy a Flask app to a production Mac Mini on the local network — a workflow that's been working for weeks.

Expected behavior

Claude Code running inside Claude Desktop should be able to reach hosts on the local network, as it did before this update. At minimum, there should be a user-facing setting to allow LAN access.

Workaround

Run Claude Code from the CLI (claude command in terminal) instead of Claude Desktop — the CLI does not have the network sandbox.

View original on GitHub ↗

12 Comments

mc0leman · 6 months ago

I believe I found the same issue — Claude Desktop MCP servers can't reach local network (192.168.x.x)

Ran into this today trying to connect a Home Assistant MCP server to Claude Desktop on Darwin 25.4.0 / MacBook Pro Intel 16,1.

I closed my bug as a duplicate, referenced here for more info/different use case: https://github.com/anthropics/claude-code/issues/44556

Any MCP server subprocess (uvx, Python venv, mcp-proxy) fails immediately with httpx.ConnectError: All connection attempts failed when trying to reach a LAN IP. Same binaries work fine from Terminal with identical env vars.

Spent a while ruling things out before finding this issue:

  • Not an App Sandbox issue — codesign -d --entitlements shows no com.apple.security.app-sandbox
  • Local Network TCC permission is enabled for Claude Desktop in System Settings
  • tccutil reset LocalNetwork fails with exit code 70
  • Tried uvx, Python 3.13 venv, mcp-proxy — all fail identically
  • Failure is instant (not a timeout), suggesting EHOSTUNREACH/ENETUNREACH at the OS level

The OPERON_SANDBOXED_NETWORK=1 env var mentioned in this issue explains everything. Subprocesses inherit that env and get network-sandboxed, blocking LAN routing entirely.

Workaround that works: HA's native MCP server supports a direct HTTP connection ("type": "http" in ~/.claude/settings.json). Claude Code CLI uses this natively without spawning a subprocess, so it bypasses the sandbox entirely. Claude Desktop has no equivalent — any stdio MCP server is broken on LAN.

This is a significant regression for anyone using locally-hosted MCP servers. Would be great to see either an allowlist mechanism for specific LAN subnets, or a way to opt specific MCP servers out of network sandboxing.

ssjoholm · 6 months ago

Confirmed reproduction on Claude Desktop 1.1062.0 (MCP remote servers on LAN blocked)
Same issue affecting remote MCP servers configured via mcp-remote in claude_desktop_config.json. All connections to local network addresses (192.168.x.x) fail with EHOSTUNREACH when spawned through Claude Desktop, while the same command works fine from a regular terminal.

Reproduction:

# Fails when run through the disclaimer helper (how Claude Desktop spawns processes):
/Applications/Claude.app/Contents/Helpers/disclaimer node -e \
  "const net = require('net'); const s = net.createConnection({host: '192.168.99.39', port: 8786}); \
  s.on('connect', () => { console.log('connected'); s.destroy(); }); \
  s.on('error', e => console.log('error:', e.message));"
# → error: connect EHOSTUNREACH 192.168.99.39:8786

# Works fine from terminal:
node -e "const net = require('net'); const s = net.createConnection({host: '192.168.99.39', port: 8786}); \
  s.on('connect', () => { console.log('connected'); s.destroy(); }); \
  s.on('error', e => console.log('error:', e.message));"
# → connected

Key finding: The disclaimer binary has no bundle ID (kMDItemCFBundleIdentifier = null) and no network entitlements, so macOS cannot grant it local network access through the normal Privacy & Security permissions panel — Claude does not appear in the Local Network list at all.

Impact: Any MCP server running on the local network and configured via mcp-remote is completely unreachable. External HTTPS servers work fine (e.g. Home Assistant via duckdns). Only RFC1918 addresses are blocked.
Environment: macOS, Claude Desktop 1.1062.0, mcp-remote 0.1.38

michaelkamprath · 6 months ago

Additional affected use case: stdio MCP servers for local home automation

I'm hitting this same issue on Claude Desktop 1.3109.0 / macOS 26.4.1 (Build 25E253, x86).

In my case the regression breaks stdio MCP servers entirely — not just Claude Code's bash tool. Specifically:

  • homeassistant-mcp (Python/pipx) connecting to https://192.168.1.26:8123
  • frigate-mcp (Python/venv) connecting to http://192.168.1.26:5000

Both were working correctly before the update. Both now fail with Errno 65: No route to host / httpx.ConnectError: All connection attempts failed.

Confirmed root cause via direct reproduction

# Succeeds — direct execution:
/path/to/python -c "import socket; socket.create_connection(('192.168.1.26', 8123))"

# Fails with Errno 65 — spawned via disclaimer:
/Applications/Claude.app/Contents/Helpers/disclaimer /path/to/python -c \
  "import socket; socket.create_connection(('192.168.1.26', 8123))"

The disclaimer helper — which Claude Desktop uses to spawn all stdio MCP server processes — is the vector. It causes the child process to lose the Local Network entitlement. OPERON_SANDBOXED_NETWORK is NOT SET in the environment of the disclaimed process, so this appears to be enforced purely at the macOS sandbox profile level, not via the env var.

Setting OPERON_SANDBOXED_NETWORK=0 in the MCP server's env block in claude_desktop_config.json has no effect.

Impact

This completely breaks any stdio MCP server that connects to local network resources — home automation, local databases, NAS devices, etc. There is currently no workaround within Claude Desktop's configuration.

ibmua · 5 months ago

Additional affected surface: Claude Desktop's built-in SSH remote workspaces (/ssh:user@host:/path)

Confirming this regression on Claude Desktop 1.3561.0 / macOS also breaks a third surface beyond the ones discussed above (Bash-tool ssh/ping/curl and stdio MCP servers): Claude Desktop's first-party SSH remote workspace feature. Different code path, different enforcement layer, same root cause.

Symptom

Any /ssh:user@host:/path workspace pointing at a LAN host fails immediately with EHOSTUNREACH:

[SSH2Connection] Resolved tr@tr -> tr@192.168.50.100:22 (identityFiles: 1)
[SSH2Connection] Connecting to tr@192.168.50.100:22 (agent: true, keys: 1, proxy: false, keyboard: true)
[SSH2Connection] Connection error: connect EHOSTUNREACH 192.168.50.100:22 - Local (192.168.50.195:51510)
[RemoteServerController] Connection failed (16ms, trigger: send_message): connect EHOSTUNREACH 192.168.50.100:22

(~/Library/Logs/Claude/ssh.log)

Different code path than the disclaimer issue

SSH2Connection and RemoteServerController run inside Claude Desktop's main process — there is no Contents/Helpers/disclaimer involved on this path. Network I/O is routed through Chromium's network-service helper:

Claude Helper --type=utility --utility-sub-type=network.mojom.NetworkService
              --service-sandbox-type=network --seatbelt-client=...

That helper has its own Seatbelt sandbox profile compiled into the build, and it appears to apply the same RFC1918 block.

Confirms env-var workaround is partial

Reproducing what others found re OPERON_SANDBOXED_NETWORK=0:

  • Launching with OPERON_SANDBOXED_NETWORK=0 open -a Claude does propagate the override (verified — a Bash tool call in the running session reports echo $OPERON_SANDBOXED_NETWORK → 0).
  • A node -e "require('net').createConnection({host:'192.168.50.100',port:22})..." from a Bash subprocess succeeds under the override (so for at least some subprocess paths the env override does help, contrary to what you'd expect from earlier comments — possibly varies by how the subprocess is launched).
  • But SSH2Connection in the main process still fails with EHOSTUNREACH — the network-helper sandbox doesn't read the env var.

So there are at least three enforcement layers active, and they don't all respond to the same knobs:

  1. disclaimer-spawned MCP subprocesses → blocked at macOS sandbox profile attached to the disclaimer helper (no env-var opt-out)
  2. Bash-tool subprocesses → in some setups respond to OPERON_SANDBOXED_NETWORK=0
  3. Main-process Chromium NetworkService (used by SSH workspaces, and presumably any future built-in network feature) → has its own baked-in Seatbelt profile, ignores env vars entirely

OPERON_* env-var audit

I grepped every OPERON_* symbol in app.asar looking for an allow-list / per-host opt-out. Result: only the binary OPERON_SANDBOXED_NETWORK flag exists. No OPERON_ALLOWED_HOSTS, no per-CIDR mechanism, no Settings UI toggle.

Impact for SSH workspaces specifically

For users with self-hosted dev machines on LAN (workstation, Jetson, Mac Mini server, NAS, etc.), SSH remote workspaces are completely unusable on Claude Desktop until this is addressed. Current workarounds:

  • Downgrade to 1.3109.0 and disable auto-update.
  • Use the standalone claude CLI (no Operon sandbox).
  • Tunnel the LAN host through Tailscale / Cloudflare Tunnel to a non-RFC1918 address — block appears specific to RFC1918, so a 100.x Tailscale address slips through.

Requested fix (echoing earlier comments)

Either an allow-list mechanism (per-host or per-CIDR, e.g. OPERON_ALLOWED_HOSTS=192.168.50.0/24) or a Settings toggle to disable the network sandbox entirely, applied consistently across all three enforcement layers above.

ibmua · 5 months ago

Update: connection succeeded after no code/config change

Following up on my SSH-workspace report above — without changing anything in Claude Desktop's config, env, or version, SSH workspace connections to the same 192.168.50.100 host started succeeding. The only thing I changed in my physical setup around the same time was plugging the MacBook into power; that may well be coincidence rather than causal.

Things I did not change between failure and success:

  • Claude Desktop version (still 1.3561.0)
  • OPERON_SANDBOXED_NETWORK env (still 0 from the launch override)
  • Network: same Wi-Fi, same subnet, same target host, same SSH config
  • No restart of Claude Desktop, no restart of the SSH target host

Possible explanations worth considering:

  • The block isn't fully deterministic — could be a race condition or a state that gets initialized lazily
  • Some macOS power-state-linked network stack behavior (Low Power Mode disables certain background networking; transitioning out of it on AC power could change network-extension / firewall behavior)
  • Local Network TCC prompt got resolved silently in the background
  • Server-side feature flag rollout / rollback rather than client behavior

Logging this in case anyone else sees intermittent rather than total failure — it may help narrow down which of the three enforcement layers is actually firing in their case.

JuHwon · 5 months ago

Additional affected surface: Vite dev proxy → LAN/private QA backend

Hitting this on Claude Desktop's built-in terminal (macOS, Darwin 25.x, Apple Silicon). Same root cause — OPERON_SANDBOXED_NETWORK=1 blocking IPv4 connects to a private subnet — but a different workflow than the MCP / SSH / /ssh: ones already reported here. Flagging because it's a very common frontend dev pattern and the failure mode looks like a Vite config bug, which costs hours of debugging.

The workflow this breaks

Frontend repo with a Vite dev server that proxies /api/* to a private-IP QA backend, so the auth cookie is set on localhost:5173 and survives reload:

// vite.config.ts (abridged)
export default defineConfig(({ command }) => ({
  server: command === 'serve' ? {
    proxy: {
      '/api': {
        target: 'http://192.168.69.21', // QA backend on LAN
        changeOrigin: true,
      },
    },
  } : undefined,
}));

Symptom

Vite dev server starts fine, but every proxied request dies in the Node proxy process:

[vite] http proxy error: /api/auth/v1/refresh
Error: connect EHOSTUNREACH 192.168.69.21:80 - Local (192.168.69.92:49273)
    at internalConnect (node:net:1115:16)

The browser sees a hung request / 502; no authentication flow works.

Reproduction — same machine, same user, same minute, same subnet

| Process parent | Command | Result |
| --- | --- | --- |
| Claude Desktop built-in terminal | npm run dev (Vite 7.1.5, Node 22.13.1) | EHOSTUNREACH on every /api/* request |
| Claude Desktop built-in terminal | curl http://192.168.69.21/ | HTTP 200 ✓ (curl isn't affected? or is it, transiently) |
| Claude Desktop built-in terminal | node -e "http.request({host:'192.168.69.21',port:80…}).end()" | succeeds from raw Node, fails from http-proxy — suggests the block triggers on specific socket-creation code paths but not others, which matches the "it's non-deterministic" observation in the earlier SSH update above |
| iTerm2 | npm run dev (identical repo, identical config) | works instantly, no errors |
| iTerm2 | curl, raw-node, everything | works |

So the filter is clearly scoped to processes spawned by the Claude Desktop app, not to the user, network, binary, or command.

Why this one deserves a separate call-out

The existing reports on this issue are about things that look obviously network-y (SSH, ping, MCP servers connecting to home-automation hubs). Those are easy to attribute correctly once you know LAN is blocked.

A Vite dev proxy isn't obviously "LAN access" — developers think of it as "my framework's config". The symptom surfaces as:

  1. A Vite-emitted error in the terminal ([vite] http proxy error)
  2. A browser-side hang / 502 / "the backend is broken"
  3. curl to the same target works, which makes the user conclude it must be a Node / Vite / http-proxy-3 bug

I spent ~2 hours chasing this in the Vite config — trying autoSelectFamily: false, pinning family: 4, custom http.Agent with keepAlive: false, bypass rules — all pointless, because the packet never leaves the sandboxed process. The failure is 100% silent from the user's perspective that anything sandbox-related is happening.

Feature requests (ranked by effort-to-value)

  1. Surface the block in the UI. When a process spawned from Claude Desktop's terminal gets EHOSTUNREACH to an RFC 1918 address, show a one-line inline hint: "Private-IP destination blocked by Claude Desktop sandbox. Run in iTerm2/Terminal.app to bypass." This alone would have saved me the two hours.
  2. Per-pane opt-out toggle. A setting on the terminal pane ("Allow LAN access — this pane will bypass the sandbox") that unsets OPERON_SANDBOXED_NETWORK and launches the shell outside the restricted profile. Acknowledge the security tradeoff in the UI.
  3. "Open in external terminal" button. One-click action on the terminal pane that runs open -a iTerm . (or the user's configured terminal) in the workspace cwd. Not a fix but a reliable escape hatch that's visible instead of tribal knowledge.
  4. Document the restriction. A docs page saying "built-in terminal cannot reach private IPv4 ranges; use a standalone terminal for LAN/VPN work" with the current workaround list.

For now the workaround for anyone else landing here via search: open -a iTerm . from the Claude terminal spawns iTerm2 as a top-level LaunchServices process (no sandbox inheritance), npm run dev there, and everything works. Note this is necessary even for frontend-only workflows as long as the dev proxy points anywhere that isn't public internet or loopback.

maltokyo · 5 months ago

crazy that this is still open

ibmua · 5 months ago

Yeah, also when I mount a pc via smb/nfs/sftp, if I work with a project on that computer, if I have connection issues, mac apps such as claude gui app basically freeze until force killed.

zupd · 4 months ago

I notice the same thing in Claude Code CLI when using sandbox mode. prob a different issue, but still, very annoying that you cant even add allowedDomains * to fix the problem, since it doesnt apply to loopback interfaces.

kaanow · 4 months ago

Confirming this on macOS (Claude desktop app — version Claude 1.8555.2 (a476c3) 2026-05-22T23:04:37.000Z), targeting a Raspberry Pi (Ubuntu 22.04, aarch64) at 192.168.4.226 on the same /24 as the host.

From Terminal, all of the following succeed against the same target:

  • ping -c 3 192.168.4.226 → 0% loss, ~5 ms
  • nc -vz 192.168.4.226 22 → succeeded
  • ssh user@192.168.4.226 → connects normally
  • arp -n 192.168.4.226 → resolves

From the Claude Code desktop app, attempting to open the same host as a remote workspace fails immediately with connect EHOSTUNREACH 192.168.4.226.

No VPN active. Three active interfaces on the Mac (en0 plus two others). Default route is via 192.168.4.1 on en0, same subnet as the Pi.

madeinoz67 · 3 months ago

Confirming this issue on both Claude Desktop and claude-code cli running in terminal, enabling the terminal under the MacOS local network security did not resolve

For me a work around for one of my internal MCP service was to use the tailscale address of the device hosting the service which is not local RFC1918 addressing and is whats sandboxed. (seems ridiculous to route over tailscale when hosting on local subnet I know!) obviously both devices need to be on the tailnet

I still have the same issue for another MCP service on another host that is not on tailscale

Also confirmed that running a local redirect proxy on localhost also worked as a workaround, however this is not a solution moving forward.

madeinoz67 · 3 months ago

Further to my last comment;

working remotely today and the tailscale fix failed, whil my other remote service (on differnt host) worked. reverting back to my original self-hosted ip address worked (working via tailscale routing), this seems to indicate the local net security issue of MacOS, yet again, everything is enabled, so only workaround is a local proxy service running on localhost that just forwards requests to the remote service until this is resolved

Showing cached comments. Read the full discussion on GitHub ↗