fix(android): block loopback canvas navigation#99874
Conversation
|
Codex review: stale review; fresh review needed. Summary Next step Review history (3 earlier review cycles) |
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
Live proof (local Android emulator)Environment: Windows, Android Studio JBR, AVD Unit (PR branch
|
| Case | Input URL | Blocked | Resolved load |
|---|---|---|---|
| loopback | http://127.0.0.1:18789 |
true |
scaffold (currentUrl=null) |
| remote | https://example.com/canvas |
false |
remote (currentUrl=https://example.com/canvas) |
Device JSON result:
{"ok":true,"mode":"canvasProof","cases":[{"label":"loopback","inputUrl":"http://127.0.0.1:18789","blocked":true,"currentUrl":null,"loadKind":"scaffold"},{"label":"remote","inputUrl":"https://example.com/canvas","blocked":false,"currentUrl":"https://example.com/canvas","loadKind":"remote"}]}Redacted logcat excerpts:
I/CanvasE2E: PASS {"ok":true,"mode":"canvasProof",...}
D/OpenClawCanvas: load scaffold: file:///android_asset/CanvasScaffold/scaffold.html
D/OpenClawCanvas: load url: https://example.com/canvas
This confirms the PR behavior on device: loopback canvas navigation falls back to the bundled scaffold, while a normal remote canvas URL is still accepted.
Repro script (local): scripts/repro/android-canvas-loopback-live-proof.ps1
@clawsweeper re-review
|
Land-ready maintainer rewrite for final head
Proof:
Known gap: source-blind exact-head validation is blocked without an interactive Android runtime plus controlled redirect, non-GET, LAN/mDNS, and loopback fixtures; those clauses are supported by source-aware tests/build/review, not claimed as live proof. Maintainer-owned changelog credit will follow in the consolidated Android batch. Thanks @ly85206559 for the original report and patch. |
* origin/main: (1287 commits) fix(android): block loopback canvas navigation (openclaw#99874) fix(hooks): suppress unhandled stdout/stderr stream errors in gmail watcher (openclaw#100519) fix(memory-core): guard qmd mcporter JSON.parse against non-JSON stdout (openclaw#98381) fix(build): fall back to tsx for build TypeScript scripts (openclaw#91262) feat(skills): suggest saving detected reusable workflows by default (openclaw#95477) (openclaw#100692) docs(changelog): remove generated release-note entries feat(telegram): offer BotFather web app flow in setup help and docs (openclaw#100540) fix(ios): unify Talk and Settings row typography on one branded detail row (openclaw#100515) feat(gateway): add persisted crash-loop breaker and fatal-config exit contract refactor(macos): lock and unify PortGuardian tunnel record persistence so concurrent app instances cannot lose orphan records (openclaw#100601) fix: stop reconnecting on protocol mismatch (openclaw#98414) fix(maint): reuse recent hosted gates after rebase (openclaw#100663) fix(ui): reopen web terminals without stale content (openclaw#100665) fix(browser): diagnose empty WSL2 Chrome replies (openclaw#100590) fix(ios): chat snaps back to bottom when scrolling to top via status-bar tap (openclaw#100502) Treat already-compacted CLI compaction as no-op (openclaw#99136) docs(changelog): remove direct main fix entry fix(feishu): strip internal tool-trace banners from outbound text (openclaw#98705) fix(message): thread --limit through to CLI formatter and surface provider pagination hints (openclaw#99089) fix(voyage): close response body stream when batch output JSONL parsing throws (openclaw#98840) ... # Conflicts: # extensions/memory-wiki/package.json
* fix(android): block loopback canvas navigation * fix(android): reject Unicode canvas hosts * chore(android): sync app changelog * style(android): format canvas navigation policy * chore(docs): sync generated docs map * chore(ci): sync hosted gate verifier --------- Co-authored-by: Peter Steinberger <[email protected]>
* fix(android): block loopback canvas navigation * fix(android): reject Unicode canvas hosts * chore(android): sync app changelog * style(android): format canvas navigation policy * chore(docs): sync generated docs map * chore(ci): sync hosted gate verifier --------- Co-authored-by: Peter Steinberger <[email protected]>
What Problem This Solves
Android Canvas navigation could reach loopback services on the device. The original guard covered gateway-driven
canvas.navigatecalls, but WebView user/JavaScript navigation, redirects, unspecified addresses, Unicode-normalized hosts, and non-GET main-frame requests left bypasses or ambiguous coverage.Why This Change Was Made
The maintainer rewrite gives direct loads and WebView main-frame navigation one policy owner:
localhostand subdomains, unspecified addresses, IPv4/IPv6 loopback, IPv4-compatible/mapped IPv6, Chromium decimal/octal/hex/shorthand IPv4 forms, encoded equivalents, and malformed HTTP(S) hosts.localhostor127.0.0.1bypasses while keeping ASCII punycode usable.shouldOverrideUrlLoading.10.0.2.2emulator host bridge, bundled app-owned Canvas URLs, blank input, and/.This is intentionally a main-frame Canvas navigation boundary, not a claim that the WebView client is a complete subresource network firewall. No permission, config, protocol, dependency, or command surface is added.
User Impact
Blocked device-local main-frame targets return to the bundled Canvas instead of loading the target. Remote and gateway-host Canvas pages continue to work, including the Android emulator host bridge.
Evidence
Final head:
dc58b11f7f148b86b188acbc5ff2e22caccd845e.cbx_e9f25743d263, runrun_a58919388153: exact code head802a3cc39808c59af270d2da818d86bc1b30acbbpassed both debug-flavor unit suites andassemblePlayDebug(78 tasks); a subsequent fullktlintFormatleft both touched policy/test files unchanged. The final head differs only by syncing generateddocs/docs_map.mdand the hosted-gate verifier to currentmainafter upstream drift.28773495496and Workflow Sanity28773495483.127.0.0.1rejection and normal remote Canvas retention: fix(android): block loopback canvas navigation #99874 (comment)Source-blind exact-head validation is blocked because no interactive Android emulator/device with controlled redirect, non-GET, LAN/mDNS, and loopback fixtures was available. The final mechanism is covered by focused source-aware regression tests, exact-head Android build/unit proof, and deep review.
AI-assisted: yes. The contributor implementation was deeply reviewed and substantially hardened by a maintainer agent before exact-head validation.