Repository navigation
fix(desktop): the WSL backend binds loopback when network access is off - #31221
THEtheChad wants to merge 3 commits into
Conversation
With Network access off, the desktop-managed WSL backend still bound 0.0.0.0 while Settings said "Limited to this machine". It now uses the Network access bind host whenever Windows reaches it over loopback (mirrored networking, or no distro IP). NAT setups, where Windows reaches the distro IP, keep 0.0.0.0 until loopback-first lands (pingdotgg#13745). Part of pingdotgg#9056 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…istro Base the loopback decision on the shared-network-stack and missing-distro-IP facts instead of the chosen renderer URL, so it still holds once the desktop prefers loopback with a distro-IP fallback (pingdotgg#13745). Cover mirrored mode and assert the renderer URL alongside the bind host. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ApprovabilityVerdict: Needs Human Approval Macroscope's review found this PR requires human approval — The WSL backend now honors local-only exposure when Windows connects through loopback, while preserving wildcard binding for NAT connections. This changes effective default listener reachability on affected WSL configurations and requires confirmation of that behavior. You can add or adjust custom eligibility rules. Learn more. |
|
No actionable comments were generated in the recent review. Walkthrough
Merge Risk:
|
Dismissed: unsolicited automated review from a blocked account.
Problem
With the desktop app's WSL backend and Network access off, Settings → Connections says "Limited to this machine", but the backend listens on
0.0.0.0and answers on every interface the distro has (tailnet, LAN, Docker bridge). Reported in #9056.resolveWslStartConfighard-coded0.0.0.0and never read the Network access setting.Change
The WSL bind host now follows the Network access setting whenever Windows reaches the backend over loopback:
127.0.0.1127.0.0.1(was0.0.0.0)0.0.0.0127.0.0.1(wslhost forwarding)127.0.0.1(was0.0.0.0)0.0.0.00.0.0.0(unchanged)0.0.0.0This doesn't fix NAT, the reporter's setup. In NAT the desktop connects to the distro IP, which a loopback bind can't serve. #13745 makes NAT try loopback first, but it keeps
0.0.0.0for its distro-IP fallback, so NAT stays on0.0.0.0even after #13745 unless that fallback is dropped. I left that trade-off to maintainers, which is why this PR says "Part of" and doesn't close the issue.Interaction with open PRs: the decision uses the underlying facts (
usesSharedNetworkStack, missing distro IP), not the chosen URL. With #13745's always-loopback primary URL, NAT still keeps0.0.0.0, so its fallback isn't broken. The two PRs touch the same block, so whichever lands second needs a small textual rebase. With #23030, Network access on still binds0.0.0.0in every mode, so the WSL Tailscale address it advertises stays reachable.Merge danger: a two-way door. The blast radius is WSL-backend users with Network access off on mirrored networking or a failed distro-IP lookup. Their backend stops answering on non-loopback interfaces, and the desktop never used those. Changing the setting already relaunches the app, which re-resolves the bind host.
Scope and approval
This is a small, focused fix for an obvious bug, filed under the exception in CONTRIBUTING. The UI states a property the bind doesn't have, and the fix makes the bind follow the existing setting, with no new behavior or settings. Bug report: #9056. Out of scope: NAT (above), and the macOS label mismatch in the issue's comments (a separate symptom).
Verification
Test:
resolveWsl binds loopback only when network access is off and Windows uses it(DesktopBackendConfiguration.test.ts) is a table of four rows: failed lookup, mirrored, NAT, and Network access on. It asserts the renderer URL host together with the bind host.network access bind 127.0.0.1, distro IP none: expected { url: '127.0.0.1', bind: '0.0.0.0' } to deeply equal { url: '127.0.0.1', bind: '127.0.0.1' }vp run check:changed: format, lint, knip, typecheck (2 packages) and tests all pass.Runtime transcript: Windows 11, WSL 3.0.3 in mirrored networking, Ubuntu 24.04. The server ran from source (
t3 serve --mode desktop) on two spare ports, one per bind host. The status is HTTP fromcurl, and000means unreachable.Windows still reaches a loopback-bound backend, the path the desktop uses in mirrored mode, while the tailnet, LAN and Docker-bridge interfaces stop answering. On this host the Hyper-V firewall for WSL blocks inbound traffic by default (
DefaultInboundAction: Block), so another LAN machine couldn't reach either port. Hosts with inbound rules, an in-distro Tailscale, or containers on the same box are where0.0.0.0leaks.Not checked: a real desktop app running a WSL backend (the transcript runs the server directly with each bind host), and the failed-lookup route on a NAT host. That route relies on wslhost loopback forwarding, which the desktop already used before this change.
Review
Two review rounds by GPT-6 Astra (Codex) and Muse Wonder Full: 5 findings accepted, 2 declined, 0 deferred.
Declined
DesktopServerExposureonly emits127.0.0.1or0.0.0.0. A LAN-IP mode would need its own WSL design, so this is speculative.bootstrap, and the neighboring WSLENV test has the same shape. Driving the full launch path adds harness setup without extra coverage today.Part of #9056
Implementation: Claude Opus 5.5 in T3 Code (Claude Code harness). Reviewed with GPT-6 Astra (Codex) and Muse Wonder Full.
🤖 Generated with Claude Code