fix #90668: [Bug]: macOS node mode can silently self-reconnect in a healthy direct gateway session#90736
fix #90668: [Bug]: macOS node mode can silently self-reconnect in a healthy direct gateway session#90736zhangguiping-xydt wants to merge 2 commits into
Conversation
|
Codex review: passed. Reviewed June 5, 2026, 10:16 PM ET / 02:16 UTC. Summary PR surface: Other +78. Total +78 across 2 files. Reproducibility: yes. source-reproducible: current main creates a fresh TLS session box on every macOS wss loop pass, and GatewayNodeSession treats the changed session identity as reconnect input. I did not run the macOS app locally during this read-only review. Review metrics: none identified. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Next step before merge
Security Review detailsBest possible solution: Merge the scoped macOS coordinator cache after the normal automerge/check gates, preserving GatewayNodeSession’s shared behavior that a genuinely changed session object triggers reconnect. Do we have a high-confidence way to reproduce the issue? Yes, source-reproducible: current main creates a fresh TLS session box on every macOS wss loop pass, and GatewayNodeSession treats the changed session identity as reconnect input. I did not run the macOS app locally during this read-only review. Is this the best way to solve the issue? Yes, this is the best fix shape: it stabilizes identity at the macOS coordinator owner boundary while leaving the shared GatewayNodeSession changed-session contract intact. The iOS sibling path already captures and reuses a sessionBox for its loop, so a shared-session change would be broader than needed. AGENTS.md: found and applied where relevant. Codex review notes: model gpt-5.5, reasoning high; reviewed against 3a2f54e6a866. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Other +78. Total +78 across 2 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
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper automerge |
|
🦞🔧 Source: I will update this PR branch, or open a safe credited replacement, if the repair worker finds a narrow CI fix. Automerge progress:
|
|
ClawSweeper 🐠 reef update Thanks for the work on this. ClawSweeper could not push to this branch with the permissions available, so it opened a narrow replacement PR to keep the fix swimming forward without losing the contributor trail. not your fault, just GitHub branch-permission tides. Why replacement: ClawSweeper could not update the source PR branch directly; GitHub did not grant sufficient push rights to the bot for that branch.
fish notes: model gpt-5.5, reasoning high; reviewed against 1496eac. |
Summary
wss://gateway loops could rebuild the TLS-pinning WebSocket session object every pass, makingGatewayNodeSessiontreat unchanged inputs as reconnect input and repeat connected notifications.wss://inputs keep the same session identity while changed trust inputs still rebuild it.apps/macos/Sources/OpenClaw/NodeMode/MacNodeModeCoordinator.swiftnow owns a narrow TLS session cache, andapps/macos/Tests/OpenClawIPCTests/MacNodeModeCoordinatorTests.swiftcovers reuse and rebuild cases.wss://path, shared reconnect semantics, config shape, or non-macOS client behavior changed.Fixes #90668
Real behavior proof
wss://loops no longer supply a fresh TLS-pinning session identity on each pass, so unchanged connection inputs do not repeatmac node connected to gatewaynotifications.619590e.openssl req -x509 -newkey rsa:2048 -sha256 -days 7 -nodes \ -keyout /Users/zhangguiping/daily_pr_work/proofs/openclaw-issue-90668-evidence/gateway-key.pem \ -out /Users/zhangguiping/daily_pr_work/proofs/openclaw-issue-90668-evidence/gateway-cert.pem \ -subj /CN=127.0.0.1 -addext subjectAltName=IP:127.0.0.1,DNS:localhost env -C /Users/zhangguiping/daily_pr_work/openclaw-90668 \ OPENCLAW_CONFIG_PATH=/Users/zhangguiping/daily_pr_work/proofs/openclaw-issue-90668-evidence/openclaw.json \ OPENCLAW_STATE_DIR=/Users/zhangguiping/daily_pr_work/proofs/openclaw-issue-90668-evidence/state \ pnpm openclaw gateway --port 19891 --bind loopback --token proof-token-90668 \ --allow-unconfigured --verbose --ws-log compact env PROOF_GATEWAY_URL=wss://127.0.0.1:19891 \ PROOF_GATEWAY_TOKEN=proof-token-90668 \ PROOF_GATEWAY_FINGERPRINT=c60afe1c23e7291a557b6ad32fea336e03d08d6466bacabcf4dd06c086e7d780 \ swift run --package-path /Users/zhangguiping/daily_pr_work/proofs/openclaw-issue-90668-evidence OpenClawNodeProof gh pr checks 90736 --repo openclaw/openclawGatewayTLSPinningSessioneach pass produced three distinct session identities and three connected callbacks. The patched cache loop reused one session identity across three healthy directwss://connect passes and produced exactly one connected callback while the gateway kept the WebSocket connected until the harness disconnected.GatewayNodeSession+GatewayTLSPinningSessionmacOS runtime path used by the coordinator against a real local OpenClaw WSS gateway. Localswift test --package-path apps/macos --filter MacNodeModeCoordinatorTestsis blocked here by Command Line Tools missing SwiftUI preview macro plugins; the PRmacos-swiftcheck passed for this head.Regression Test Plan
apps/macos/Tests/OpenClawIPCTests/MacNodeModeCoordinatorTests.swiftwss://node-mode loop passes with the same URL and TLS params reuse one session object; changed TLS fingerprint input rebuilds it.GatewayNodeSession.connect(...), so it proves the exact identity-stability invariant without weakening the shared gateway reconnect contract.Root Cause
MacNodeModeCoordinator.run()calledbuildSessionBox(...)on every loop pass, and thewss://path created a freshGatewayTLSPinningSession/WebSocketSessionBoxfor unchanged URL and TLS pin inputs.