#22056: fix(gateway): use loopback for self-connections regardless of bind mode
gateway
size: S
Cluster:
Gateway Resilience and Configuration
## Problem
Closes #22047
`bind: "lan"` causes the browser tool (and any Gateway self-connection) to fail with a `SECURITY ERROR` after the plaintext ws:// block introduced in #20803.
Two commits are in conflict:
- **#11448** — `localUrl` now uses the LAN IP when `bind=lan`
- **#20803** — plaintext `ws://` to non-loopback addresses is rejected
Result: agents running on the **same host** as the Gateway hit `SECURITY ERROR: Gateway URL "ws://192.168.x.x" uses plaintext ws:// to a non-loopback address.`
## Fix
`localUrl` in `buildGatewayConnectionDetails()` always uses `ws(s)://127.0.0.1:<port>` regardless of bind mode.
`bind` controls which interface the **server** listens on — it should not affect the connection URL for agents on the same host. LAN/tailnet IPs are still available in `lanIPv4` / `tailnetIPv4` for display purposes (QR codes, `urlSource` labels, onboarding hints).
## Changes
- `src/gateway/call.ts`: `localUrl` simplified to `ws(s)://127.0.0.1:${localPort}`
- `src/gateway/call.test.ts`: updated test names and assertions to reflect new behavior
## Tests
```
✓ src/gateway/call.test.ts (29 tests) 167ms
```
All 29 tests passing.
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Fixes a regression where `bind: "lan"` caused browser tools and Gateway self-connections to fail with `SECURITY ERROR` due to a conflict between two previous commits. The fix ensures agents on the same host always connect via `127.0.0.1` regardless of bind mode, since `bind` controls which interface the server listens on, not the connection URL for local agents. LAN/tailnet IPs remain available for display purposes (QR codes, onboarding hints).
- Modified `buildGatewayConnectionDetails()` in `src/gateway/call.ts` to always use `ws(s)://127.0.0.1` for `localUrl`, removing the conditional logic that previously used LAN/tailnet IPs based on bind mode
- Updated all related tests in `src/gateway/call.test.ts` to reflect the new behavior, converting tests that expected `SECURITY ERROR` exceptions into tests that verify loopback connections succeed
- All 29 tests passing, confirming the fix resolves the security error while maintaining proper functionality
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with minimal risk
- The fix correctly resolves a clear regression caused by conflicting commits. The change is well-contained, maintains backward compatibility for all use cases, and actually improves security by ensuring local agents always use loopback addresses. All 29 tests pass, including updated tests that specifically verify the new behavior works correctly for all bind modes (loopback, lan, tailnet) with and without TLS. The implementation is simple, well-commented, and aligns with the security principle that ws:// to non-loopback addresses should be blocked.
- No files require special attention
<sub>Last reviewed commit: e97ebcf</sub>
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#19026: fix(gateway): use loopback for local CLI-to-gateway connections
by Phineas1500 · 2026-02-17
89.6%
#22110: fix(tools): prefer loopback for internal tool-to-gateway RPC calls
by pierreeurope · 2026-02-20
89.3%
#21436: fix(gateway): plaintext ws:// blocked for Docker bind=lan (SECURITY...
by xinhuagu · 2026-02-19
85.1%
#19437: Gateway: respect custom bind host for local health/RPC target resol...
by frudas24 · 2026-02-17
85.0%
#21233: docs: clarify bind=lan non-loopback access requires wss or tunnel (...
by saurabhchopade · 2026-02-19
82.9%
#14564: fix(gateway): crashes on startup when tailscale meets non-loopback ...
by yinghaosang · 2026-02-12
82.3%
#22804: fix: prioritize loopback for internal gateway calls (issue #22706)
by ambicuity · 2026-02-21
82.3%
#16300: fix(tui): respect gateway bind mode in TUI connection
by cortexuvula · 2026-02-14
81.6%
#21256: fix: treat ws:// to Tailscale addresses as secure when bind=tailnet
by jessewunderlich · 2026-02-19
80.8%
#21784: fix(security): restrict gateway ports to loopback by default
by smilekyra · 2026-02-20
80.6%