Skip to content

fix(browser): ignore loopback WSL resolver hosts for launched Chrome - #324

Open
Rokurolize wants to merge 1 commit into
steipete:mainfrom
Rokurolize:codex/wsl-loopback-resolver
Open

fix(browser): ignore loopback WSL resolver hosts for launched Chrome#324
Rokurolize wants to merge 1 commit into
steipete:mainfrom
Rokurolize:codex/wsl-loopback-resolver

Conversation

@Rokurolize

@Rokurolize Rokurolize commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Problem

On WSL, launcher mode uses the first /etc/resolv.conf nameserver as the Chrome DevTools connection host. With a distro-managed systemd-resolved stub, that value is a guest-local DNS endpoint such as 127.0.0.53, not a Windows host address. Oracle therefore launches Chrome but checks the dynamic DevTools port through the DNS stub and fails before browser automation begins.

The same resolver heuristic was duplicated in the browser connectivity smoke script.

Why 127.0.0.53 can appear on WSL

This address is not assigned by WSL as the Windows host. It appears when Linux DNS management is layered on top of WSL networking:

  1. Microsoft documents that WSL supports systemd, and current Ubuntu installations made through wsl --install use systemd by default. A WSL distribution can therefore run systemd-resolved just like a regular Linux installation.
  2. Microsoft documents that generateResolvConf controls whether WSL generates /etc/resolv.conf. The reproduced distribution explicitly has systemd=true and generateResolvConf=false, so /etc/resolv.conf is managed inside the distribution and points to systemd-resolved's stub file.
  3. systemd's official resolved.conf manual defines 127.0.0.53 and 127.0.0.54, port 53, as local DNS stub listener addresses. The full resolver is exposed on 127.0.0.53; it forwards queries to the currently selected upstream DNS server.
  4. RFC 1122 section 3.2.1.3 defines every address of the form 127.<any> as internal host loopback that must not appear outside a host. A resolver-derived 127.0.0.53 therefore cannot identify a separate Windows host across the WSL network boundary.
  5. Microsoft's WSL networking guidance identifies the Windows host in NAT mode through the default route and notes that mirrored mode uses localhost. It does not define a 127/8 address other than local loopback as a remote Windows-host endpoint.
  6. Microsoft's WSL configuration reference separately documents 10.255.255.254 as the default dnsTunnelingIpAddress. On the reproduced host, systemd-resolved uses that address as its upstream DNS server while exposing 127.0.0.53 to local Linux clients.

The observed resolver chain was:

/etc/resolv.conf -> /run/systemd/resolve/stub-resolv.conf
nameserver 127.0.0.53
systemd-resolved upstream DNS server: 10.255.255.254

The old heuristic only works when the first nameserver is a reachable non-loopback host-side address. It becomes invalid when /etc/resolv.conf names a local resolver frontend. Oracle does not need to infer the complete WSL topology for this fix: rejecting resolver-derived 127/8 values is sufficient because those values are unambiguously guest loopback.

Change

This centralizes WSL host resolution, maps only resolver-derived 127/8 values to 127.0.0.1, and uses the standard local launcher for that route. Explicit ORACLE_BROWSER_REMOTE_DEBUG_HOST and WSL_HOST_IP values remain authoritative. Resolver-derived non-loopback values retain the patched remote-host launcher and 0.0.0.0 bind behavior for Windows Chrome compatibility.

The runtime and scripts/test-browser.ts now use the same resolver parser. The WSL behavior is recorded in docs/windows-work.md and the unreleased changelog.

Reproduction and live proof

The original comparison used upstream 8e3456e7 and submitted head 527857f1 on the same WSL2 host. Both host overrides were removed with env -u ORACLE_BROWSER_REMOTE_DEBUG_HOST -u WSL_HOST_IP.

Upstream, using a fixed diagnostic port:

EXPECTED_FAILURE connect ECONNREFUSED 127.0.0.53:45903

After rebasing onto 19a0b79b, I repeated the production launchChrome path on rebased head 1cd2abb8 with the same overrides unset. The live resolver was the systemd-resolved stub:

proof_head=1cd2abb8ef8e5aedb0bd21f1a09cda98aa0a9a63
resolver_host=127.0.0.53
route={"connectHost":"127.0.0.1","debugBindAddress":"127.0.0.1","usePatchedLauncher":false}
Launched Chrome (pid redacted) on port 45904 on 127.0.0.1
PATCHED_SUCCESS host=127.0.0.1 port=45904 status=200

The success status is from Chrome's live /json/version endpoint. The failed upstream launch was terminated after capture.

Validation

On rebased head 1cd2abb8, pnpm vitest run tests/browser/wslHost.test.ts tests/browser/chromeLifecycle.test.ts passes 35 tests. Coverage includes 127.0.0.53, 127.0.0.54, another 127/8 value, non-loopback preservation, explicit override precedence, explicit loopback override preservation, legacy override preservation, and local versus patched launcher routing.

pnpm check, pnpm build, and git diff --check pass.

pnpm test passes 1,601 tests in 147 files, with the existing 43 tests and 18 files skipped.

Non-goal

This does not redesign the broader WSL topology heuristic or change attach-running and explicit remote-Chrome behavior. Distinguishing native Linux Chrome, Windows Chrome, and remote Chrome using positive topology evidence remains separate work.

@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P2 Normal priority bug or improvement with limited blast radius. labels Jul 13, 2026
@clawsweeper

clawsweeper Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 31, 2026, 5:40 PM ET / 21:40 UTC.

ClawSweeper review

What this changes

The PR centralizes WSL resolver-host handling so resolver-derived 127/8 DNS stubs use Oracle’s local Chrome launcher while explicit overrides and non-loopback WSL hosts retain their existing behavior.

Merge readiness

⚠️ Ready for maintainer review - 4 items remain

Keep this PR open for maintainer review. Current main still passes the first WSL resolver address straight into the remote-host launcher, while the PR has focused tests and credible live proof for the systemd-resolved failure; the remaining question is whether changing all resolver-derived loopback cases to the local launcher is an acceptable compatibility tradeoff.

Priority: P2
Reviewed head: 1cd2abb8ef8e5aedb0bd21f1a09cda98aa0a9a63
Owner decision: Required. See Decision needed.

Review scores

Measure Result What it means
Overall readiness 🐚 platinum hermit (4/6) This is a focused, well-covered fix with strong live proof; the remaining blocker is a maintainer-owned compatibility decision rather than an identified patch defect.
Proof confidence 🦞 diamond lobster (5/6) Sufficient (live_output): The PR body includes after-fix live output from the production Chrome-launch path and a successful request to Chrome’s DevTools /json/version endpoint on the affected WSL resolver setup.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Verified Sufficient (live_output): The PR body includes after-fix live output from the production Chrome-launch path and a successful request to Chrome’s DevTools /json/version endpoint on the affected WSL resolver setup.
Evidence reviewed 6 items Current-main behavior remains unfixed: Current main takes the first IPv4 nameserver from /etc/resolv.conf without loopback normalization, then selects the patched launcher and 0.0.0.0 bind address for every host except exactly 127.0.0.1; a systemd-resolved 127.0.0.53 therefore still follows the failing route.
Submitted implementation is narrowly scoped: The proposed helper normalizes only resolver-derived 127/8 values to 127.0.0.1, preserves explicit ORACLE_BROWSER_REMOTE_DEBUG_HOST and legacy WSL_HOST_IP values, and keeps non-loopback resolver hosts on the existing patched-launcher route.
Targeted route coverage: The PR adds unit coverage for multiple loopback resolver addresses, a non-loopback resolver, override precedence, explicit loopback override preservation, and local-versus-patched launcher selection.
Findings None None.
Security None None.

How this fits together

Oracle’s browser mode launches Chrome and then connects to its DevTools endpoint for automation. On WSL, the resolver or an explicit host override determines whether Chrome uses the normal local launcher or a Windows-compatible remote-host launcher before DevTools connection begins.

flowchart LR
  A[WSL environment] --> B[Resolver or explicit host]
  B --> C[Chrome launch route]
  C --> D[DevTools endpoint]
  D --> E[Browser automation]
  F[Host overrides] --> B
Loading

Decision needed

Question Recommendation
Should Oracle make resolver-derived WSL loopback nameservers use the standard local Chrome launcher by default, with explicit host overrides remaining available for exceptional Windows Chrome routes? Accept local loopback routing: Merge the narrow normalization and retain the explicit host overrides for installations that need a Windows-side route.

Why: The patch fixes a demonstrated failure and preserves documented override precedence, but it deliberately changes the launcher and bind behavior for an existing WSL topology that current source treats as remote.

Before merge

  • Resolve merge risk (P1) - Resolver-derived loopback addresses will stop using the patched remote-host launcher and 0.0.0.0 bind path; an uncommon WSL installation that depends on a Windows-side Chrome route must instead provide ORACLE_BROWSER_REMOTE_DEBUG_HOST or WSL_HOST_IP.
  • Resolve merge risk (P1) - The contributor’s live proof demonstrates the affected systemd-resolved setup, but it cannot establish that every existing resolver-loopback topology has compatible localhost forwarding.
  • Complete next step (P2) - A browser owner needs to accept or reject the WSL launcher compatibility tradeoff; there is no narrow mechanical repair remaining for an automated worker.
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Patch scope 6 files affected; 151 added, 61 removed The implementation replaces duplicated resolver parsing with one shared helper and adds focused route tests.
Focused regression coverage 1 new test file with loopback, override, and launcher-route cases The central compatibility decision is exercised without broad unrelated refactoring.

Merge-risk options

Maintainer options:

  1. Confirm the WSL compatibility contract (recommended)
    Accept resolver-derived loopback as a local-launch signal and preserve the documented environment-variable escape hatch for unusual Windows Chrome routes.
  2. Pause for broader topology detection
    Do not merge until Oracle can distinguish the relevant WSL Chrome topology without changing existing loopback behavior by default.

Technical review

Best possible solution:

Adopt the narrow resolver-derived loopback normalization if the browser owner accepts localhost as the supported default for those WSL setups, while retaining explicit host overrides as the documented escape hatch for exceptional Windows Chrome routes.

Do we have a high-confidence way to reproduce the issue?

Yes, from source and submitted live evidence: on WSL with /etc/resolv.conf containing nameserver 127.0.0.53, current main selects that address for the remote-host launch path; the contributor recorded the resulting refusal and an after-fix live DevTools response.

Is this the best way to solve the issue?

Unclear pending the compatibility decision. The proposed normalization is narrowly implemented and preserves explicit overrides, but maintainers must decide whether resolver-derived loopback should always prefer the local launcher rather than a Windows-side route.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 68b8c51b0ee0.

Labels

Label justifications:

  • P2: This is a bounded browser-launch regression for affected WSL users, with a clear workaround but no demonstrated broad outage.
  • merge-risk: 🚨 compatibility: Resolver-derived loopback setups change from the remote patched launcher to the normal local launcher after upgrade.
  • merge-risk: 🚨 availability: Incorrect topology assumptions can prevent Oracle from reaching Chrome’s DevTools endpoint and block browser automation.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR body includes after-fix live output from the production Chrome-launch path and a successful request to Chrome’s DevTools /json/version endpoint on the affected WSL resolver setup.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes after-fix live output from the production Chrome-launch path and a successful request to Chrome’s DevTools /json/version endpoint on the affected WSL resolver setup.

Evidence

What I checked:

  • Current-main behavior remains unfixed: Current main takes the first IPv4 nameserver from /etc/resolv.conf without loopback normalization, then selects the patched launcher and 0.0.0.0 bind address for every host except exactly 127.0.0.1; a systemd-resolved 127.0.0.53 therefore still follows the failing route. (src/browser/chromeLifecycle.ts:818, 68b8c51b0ee0)
  • Submitted implementation is narrowly scoped: The proposed helper normalizes only resolver-derived 127/8 values to 127.0.0.1, preserves explicit ORACLE_BROWSER_REMOTE_DEBUG_HOST and legacy WSL_HOST_IP values, and keeps non-loopback resolver hosts on the existing patched-launcher route. (src/browser/wslHost.ts:10, 1cd2abb8ef8e)
  • Targeted route coverage: The PR adds unit coverage for multiple loopback resolver addresses, a non-loopback resolver, override precedence, explicit loopback override preservation, and local-versus-patched launcher selection. (tests/browser/wslHost.test.ts:8, 1cd2abb8ef8e)
  • Live after-fix proof: The PR body records an after-fix production launchChrome run on the affected WSL resolver setup: 127.0.0.53 resolves to the local route and Chrome’s live /json/version endpoint returns HTTP 200. (1cd2abb8ef8e)
  • Current-path provenance: git blame attributes the current resolver and launcher-selection lines to the local v0.16.1 baseline authored by Peter Steinberger; the current release tag therefore still contains the pre-fix behavior. (src/browser/chromeLifecycle.ts:818, 5daa6ce8c352)
  • Release check: No local release tag contains the PR head, and CHANGELOG.md shows v0.16.1 as the latest shipped release; this fix is neither merged into current main nor released. (CHANGELOG.md:3, 68b8c51b0ee0)

Likely related people:

  • steipete: The local v0.16.1 baseline attributes the active WSL resolver and launcher-selection lines to Peter Steinberger, and this PR changes the compatibility behavior of that browser-launch path. (role: current browser-path contributor and likely decision owner; confidence: medium; commits: 5daa6ce8c352; files: src/browser/chromeLifecycle.ts, scripts/test-browser.ts)

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

History

Review history (15 earlier review cycles; latest 8 shown)
  • reviewed 2026-07-30T15:21:59.886Z sha 1cd2abb :: needs maintainer review before merge. :: none
  • reviewed 2026-07-30T21:14:39.838Z sha 1cd2abb :: needs maintainer review before merge. :: none
  • reviewed 2026-07-31T00:01:48.198Z sha 1cd2abb :: needs maintainer review before merge. :: none
  • reviewed 2026-07-31T01:49:22.389Z sha 1cd2abb :: needs maintainer review before merge. :: none
  • reviewed 2026-07-31T11:27:32.733Z sha 1cd2abb :: needs maintainer review before merge. :: none
  • reviewed 2026-07-31T14:27:46.901Z sha 1cd2abb :: needs maintainer review before merge. :: none
  • reviewed 2026-07-31T18:46:12.888Z sha 1cd2abb :: needs maintainer review before merge. :: none
  • reviewed 2026-07-31T20:15:12.339Z sha 1cd2abb :: needs maintainer review before merge. :: none

@Rokurolize
Rokurolize marked this pull request as ready for review July 13, 2026 16:43
@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. and removed rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. labels Jul 22, 2026
@Rokurolize
Rokurolize force-pushed the codex/wsl-loopback-resolver branch from 527857f to 1cd2abb Compare July 23, 2026 05:27

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. labels Jul 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant