fix(android): reject IPv6 zone IDs in gateway endpoint URLs#99570
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 3, 2026, 2:51 PM ET / 18:51 UTC. Summary PR surface: Other +68. Total +68 across 4 files. Reproducibility: yes. for source-level reproduction: current main accepts scoped IPv6 endpoint URLs into Android gateway config, and the runtime then hands bracketed scoped hosts to OkHttp Request.Builder.url. I did not run the Android emulator in this read-only review, but I inspected the PR’s before/after emulator screenshots for the same input. Review metrics: none identified. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Mantis proof suggestion Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Reject scoped IPv6 at the shared Android endpoint parser for manual/setup/QR inputs while preserving unscoped IPv6 and existing cleartext-host rules; handle any discovered-link-local follow-up separately if it is reproducible. Do we have a high-confidence way to reproduce the issue? Yes for source-level reproduction: current main accepts scoped IPv6 endpoint URLs into Android gateway config, and the runtime then hands bracketed scoped hosts to OkHttp Request.Builder.url. I did not run the Android emulator in this read-only review, but I inspected the PR’s before/after emulator screenshots for the same input. Is this the best way to solve the issue? Yes for the changed surface: the shared parser is the right boundary for manual, setup-code, and scanned-QR endpoint URLs, and rejecting is safer than stripping an interface zone. Discovered-gateway link-local handling is an adjacent existing path, not something this PR needs to solve before merge. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against df1452799b28. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Other +68. Total +68 across 4 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
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. How this review workflow works
|
Local proof (Windows)Environment
Command cd d:\WorkSpace\AI\openclaw\.worktrees\android-gateway-ipv6-zone-host\apps\android
.\gradlew.bat :app:testPlayDebugUnitTest `
--tests ai.openclaw.app.ui.GatewayConfigResolverTest.parseGatewayEndpointAllowsLinkLocalIpv6ZoneCleartextWsUrls `
--tests ai.openclaw.app.ui.GatewayConfigResolverTest.parseGatewayEndpointAllowsSecureIpv6ZoneUrlsResult: JUnit (
|
|
@clawsweeper re-review Addressed correctness feedback in |
|
🦞🧹 I asked ClawSweeper to review this item again. |
Strip interface zones during endpoint parsing so link-local URLs like ws://[fe80::1%25eth0] connect using socket-ready literals such as fe80::1. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
56f96f4 to
9a85c54
Compare
|
Land-ready maintainer proof for exact head
Known proof boundary: no physical link-local IPv6 interface was available. The reproduced defect is the production UI accepting and persisting an endpoint that the Android HTTP stack cannot represent for dialing; rejection now occurs before that boundary. |
|
Merged via squash.
|
…#99570) * fix(android): normalize IPv6 zone IDs in gateway endpoint hosts Strip interface zones during endpoint parsing so link-local URLs like ws://[fe80::1%25eth0] connect using socket-ready literals such as fe80::1. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(android): reject IPv6 zone IDs in gateway endpoint URLs Co-authored-by: Cursor <cursoragent@cursor.com> * fix(android): reject scoped IPv6 gateway hosts * chore(android): sync native i18n inventory --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Peter Steinberger <steipete@gmail.com>


What Problem This Solves
Gateway endpoint URLs with IPv6 interface zones — for example,
wss://[fe80::1%25wlan0]:443— passed Android validation and were saved even though OkHttp cannot canonicalize that decoded host for a WebSocket URL. The user only learned the endpoint was unusable after onboarding advanced to connection recovery.Why This Change Was Made
Reject scoped IPv6 at the canonical endpoint parser boundary with a structured
IPV6_ZONE_ID_UNSUPPORTEDresult. Manual entry, setup codes, and scanned QR codes now preserve that reason and show source-specific replacement guidance; other malformed QR input keeps its existing setup-QR guidance.This is deliberately fail-closed. Silently stripping a zone could select the wrong link-local interface, while accepting it creates a persisted endpoint that the current OkHttp 5.3.2 URL path cannot dial.
User Impact
Scoped IPv6 gateway URLs are rejected before persistence or connection. The UI tells the user to use an unscoped IPv6 address or LAN hostname. Ordinary IPv4, hostname, and unscoped IPv6 parsing is unchanged.
Evidence
Exact head:
e81a9e806d73870140bad0aa7c231ad88f29f8fdAndroid 16 emulator before/after
Both captures use the identical input
wss://[fe80::1%25wlan0]:443.Automated proof
Both commands passed. The focused suite covers cleartext and TLS scoped hosts, unscoped IPv6, setup-code/QR error propagation, and all source-specific messages.
Fresh Codex autoreview passed in uncommitted and branch modes with no findings.