Skip to content

fix(setup): approve only the pairing request setup just opened - #1480

Closed
SebTardif wants to merge 6 commits into
openclaw:mainfrom
SebTardif:fix/setup-approve-opened-pairing-request
Closed

SebTardif wants to merge 6 commits into
openclaw:mainfrom
SebTardif:fix/setup-approve-opened-pairing-request

Conversation

@SebTardif

@SebTardif SebTardif commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

What Problem

AutoApprovePairing with no request id ran openclaw devices approve --latest before checking an id. That approves whichever pending request is newest.

Why

A local process can submit a newer loopback pairing request during setup.

User Impact

Setup now lists pending requests, keeps the operator row for the socket it just opened, and approves only that id. approve --latest is not used on this path.

Evidence

Red: AutoApprovePairing_WithoutRequestId_ApprovesOnlyTheRequestForTheOpenedSocket approved attacker-latest-req. Green: that test passed. Setup-engine suite 1192 passed. The host wsl --version UTF-16 test failed and does not touch this change. .\build.ps1 passed.

The paragraph above preserves the original author evidence. The current-head results below supersede those historical counts and the previous lack of live Gateway proof.

Bounded maintainer follow-up

Preserves SebTardif's operator, wizard-identity, and late-drain fixes. The remaining PairNodeStep.AutoApproveNodePairing fallback now reuses TrySelectPendingRequestForDevice(..., ctx.OperatorDeviceId, matchNodeId: true) instead of approving the sole pending node. The operator and node setup sockets use the same per-gateway full identity; NodeDeviceId is a shortened display value and is not approval authority. Socket-provided request IDs, unsafe-ID rejection, and plugin/list failure handling are unchanged.

Current head: edb08328e5e051c30d4604ab5527e765a0ce16ad. Integrated current main 42c562f91a42ae0251ac971c44f6ce0f8028e88d with an ordinary merge, preserving contributor history. The repair adds 14 actual approval-path regression cases and a short architecture-reference note. A second maintainer commit only replaces the fake test credential with an established explicit placeholder for review scanning.

Required proof pools

  • windows-wsl-gateway-e2e: setup operator/node pairing approval changed. Native official Gateway contract proof is recorded below; full WSL setup remains Not verified / blocked.
  • windows-wsl-mxc: repository-required gateway-to-Windows-node containment closeout remains Not verified / blocked. No MXC behavior changed and no containment claim is made.

Validation

Final-head native Windows ARM64 validation used the private .NET SDK 10.0.400, OPENCLAW_REPO_ROOT set to this isolated worktree, unique tray data/AppData directories, and E2E flags disabled. Fresh test-project builds preceded --no-restore runs. The complete floor was repeated after the fixture-only follow-up.

Command Final result
.\build.ps1 Passed, all projects and documentation gate
dotnet build .\tests\OpenClaw.Shared.Tests\OpenClaw.Shared.Tests.csproj Passed
dotnet build .\tests\OpenClaw.Tray.Tests\OpenClaw.Tray.Tests.csproj Passed
dotnet test .\tests\OpenClaw.Shared.Tests\OpenClaw.Shared.Tests.csproj --no-restore 4,096 passed, 35 skipped, 0 failed
dotnet test .\tests\OpenClaw.Tray.Tests\OpenClaw.Tray.Tests.csproj --no-restore 3,069 passed, 0 skipped, 0 failed
dotnet test .\tests\OpenClaw.SetupEngine.Tests\OpenClaw.SetupEngine.Tests.csproj --no-restore 1,213 passed, 1 skipped, 0 failed
dotnet test .\tests\OpenClaw.SetupEngine.Tests\OpenClaw.SetupEngine.Tests.csproj --no-restore --filter FullyQualifiedName~AutoApproveNodePairing 18 passed, 0 skipped, 0 failed

All test runs emitted TRX results. Before the production repair, the same focused subset produced 9 failures and 9 passes: eight behavioral failures and one changed diagnostic assertion. Afterward all 18 passed, including sole foreign pending, full nodeId/deviceId selection among foreign requests, missing/short identities, ambiguous matches, unsafe IDs, exact socket-ID routing, and existing plugin error cases. No new regression test executes a distro.

Focused rubber-duck review found no blockers. Structured autoreview used Codex 0.156.1, gpt-5.6-sol, high reasoning, with python .\.agents\skills\autoreview\scripts\autoreview --mode branch --base f613578ac17afc136d8a4da0b371309d0e59f6b3 --engine codex and the verified native Codex executable. This exact repair range excludes unchanged author/main commits. Result: no accepted/actionable findings. Dead-helper cleanup was deliberately left outside this bounded repair.

Real behavior proof

One isolated native official Gateway 2026.9.5 case ran against the current-head production assemblies. Real WindowsNodeClient handshakes created two task-owned synthetic identities and pending node surfaces by advertising system.which; no node command was invoked. Device bootstrap approval used only exact request IDs matched to those synthetic full identities. The actual openclaw nodes list --json output exposed pending[].requestId and a 64-character pending[].nodeId.

The harness called production AutoApproveNodePairing with a missing socket request ID. A constrained native ICommandRunner adapter translated only its list/approve transport to the pinned official CLI. It did not fabricate pending JSON or replace the production selector.

Actual Gateway state Observed production result
Only the task-owned foreign node pending; intended node absent Failed closed; zero approval attempts; same foreign request remained pending
Intended and foreign node both pending Approved exactly the intended request; pending count 2 to 1; intended node paired; same foreign request remained pending

Executed OpenClaw.SetupEngine.dll SHA-256: CAB04539C0A611D6AF5E954734DED4582384AEFD09D9EDE561E5B12358538664. Production PairNodeStep.cs blob: b9eb59d2289ad233130ca95b82f10f1c9eff094e. The harness and final-head test output DLL hashes match. The owned Gateway and harness processes were stopped, port 22480 had no remaining listener, and synthetic identity/profile directories were removed. No tokens, identity files, or normal user state are published.

Not verified / blocked: native CLI transport is not wsl.exe argument/environment propagation, full WSL setup, GUI/MCP smoke, or Gateway-to-node MXC containment proof. Shared-host safety rules prohibited distro startup, services, GUI, and probes. The sole allowed WSL operation was the existing wsl.exe --version decoder unit test. These limits do not convert the outstanding custom proof pools into passes. Merge and proof-pool disposition remain with the coordinating maintainer.

Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
@clawsweeper

clawsweeper Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Sep 23, 2026
@clawsweeper

clawsweeper Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

Codex review: needs real behavior proof before merge. Reviewed September 25, 2026, 9:08 PM ET / September 26, 2026, 01:08 UTC (Revision 10).

ClawSweeper review

What this changes

The setup engine selects pending operator and node pairing requests by device identity, approves exact request IDs, and limits later approval drains to matching requests.

Merge readiness

⛔ Blocked before merge - 13 items remain

This PR addresses a real pairing approval risk, but its missing-ID selector can still choose an older request with the same identity. The maintainer replacement at #1523 covers that case, but remains open without the required adversarial Gateway proof, so it is not yet a safe superseding landing path.

Priority: P0
Reviewed head: edb08328e5e051c30d4604ab5527e765a0ce16ad
Owner decision: Required. See Decision needed.

Review scores

Measure Result What it means
Overall readiness 🦪 silver shellfish (2/6) Useful targeted work and genuine node-path proof remain limited by three concrete source blockers and incomplete final-effect coverage.
Proof confidence 🦐 gold shrimp (3/6) Needs stronger real behavior proof before merge: Authority-chain proof required: The PR body describes current-head production node approval against an official Gateway, including rejection of a foreign node and approval of the intended node. It does not show allowed, foreign, and stale final effects for operator approval and later drains through the changed WSL setup path. No stored-data contract changes. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Patch quality 🦪 silver shellfish (2/6) Security review found an item that needs attention.

Verification

Check Result Evidence
Real behavior Needs proof Needs stronger real behavior proof before merge: Authority-chain proof required: The PR body describes current-head production node approval against an official Gateway, including rejection of a foreign node and approval of the intended node. It does not show allowed, foreign, and stale final effects for operator approval and later drains through the changed WSL setup path. No stored-data contract changes. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed 7 items Introduced selector: The new missing-ID selector matches the full identity and requires a unique match, but does not distinguish a request already pending before this setup socket opened.
Drain result handling: The introduced drain checks for the words 'No pending' in output before checking exit status or parsing JSON, allowing an error or JSON metadata to be mistaken for an empty queue.
WSL transport contract: The new pending-list call uses the PATH-bearing script without inputViaStdin; the command runner defaults to passing scripts through bash -c argv, which the repository documents as vulnerable to WSL variable expansion.
Findings 3 actionable findings [P1] Exclude requests pending before this socket opens
[P1] Send the changed pairing scripts through WSL stdin
[P2] Check the pending-list result before ending the drain
Security Needs attention Stale same-identity pairing approval: A request from an earlier setup attempt can share the full identity and reach the final Gateway approval command when the current socket supplies no ID.

How this fits together

Windows setup opens operator and node connections to a Gateway running in WSL. When pairing is required, the setup engine reads pending Gateway requests and sends an approval command before continuing setup.

flowchart LR
A[Setup connection] --> B[Pairing request ID]
B --> C{ID supplied?}
C -->|Yes| D[Approve exact request]
C -->|No| E[Read pending requests]
E --> F[Select by setup identity]
F --> D
D --> G[Gateway pairing state]
Loading

Decision needed

Question Recommendation
Should the maintained replacement become the sole landing path after adversarial Gateway and MXC proof, or should this original branch be repaired and proved instead? Prove and land replacement: Keep both open until the replacement demonstrates intended, foreign, and stale final effects on a real Gateway and completes required MXC validation.

Why: The replacement is technically more complete but has not met the security-boundary and repository proof gates, so choosing a landing branch requires maintainer ownership.

Before merge

  • Add real behavior proof - Needs stronger real behavior proof before merge: Authority-chain proof required: The PR body describes current-head production node approval against an official Gateway, including rejection of a foreign node and approval of the intended node. It does not show allowed, foreign, and stale final effects for operator approval and later drains through the changed WSL setup path. No stored-data contract changes. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
  • Exclude requests pending before this socket opens (P1) - The new selector accepts any unique request with the setup identity. If an older same-identity request is pending and this socket's request is delayed or absent, setup approves the older request. This concern was missed in earlier reviews of the unchanged head; capture a pre-connect baseline and reject its IDs before approval.
  • Send the changed pairing scripts through WSL stdin (P1) - The introduced pending-list and exact-approval calls use a PATH-bearing script while RunInWslAsync defaults to bash -c argv. WSL can expand $PATH before Bash receives it, breaking the pairing flow; pass inputViaStdin: true on the changed calls.
  • Check the pending-list result before ending the drain (P2) - The new drain breaks when stdout or stderr merely contains 'No pending', before checking exit status or parsing JSON. A failed command or valid JSON metadata with that phrase can silently skip a real pending request; validate the result and parse structured output first.
  • Resolve security concern: Stale same-identity pairing approval - A request from an earlier setup attempt can share the full identity and reach the final Gateway approval command when the current socket supplies no ID.
  • Resolve merge risk (P1) - A missing socket request ID can cause this branch to approve a stale request sharing the setup identity, before the current socket's request is established.
  • Resolve merge risk (P1) - The changed WSL commands still pass PATH-bearing scripts through argv, so an existing setup may fail to list or approve pairing requests under WSL expansion.
  • Resolve merge risk (P2) - Current-head real Gateway evidence covers the node fallback but not allowed and foreign final effects through operator approval and the later drains; the required no-skip MXC proof is also blocked.
  • Complete next step (P2) - Resolve the stale-request, WSL stdin, and drain parsing blockers on the chosen landing branch, then provide current-head adversarial Gateway and required MXC proof. Redact private identifiers and endpoints; updating the PR body should trigger a fresh review, or a maintainer can request @clawsweeper re-review.
  • Improve patch quality - Exclude pre-connect requests from missing-ID fallback, or carry the more complete maintained replacement.
  • Improve patch quality - Preserve WSL stdin transport and validate pending-list exit status before parsing its output.
  • Improve patch quality - Add final-effect proof for intended, foreign, and stale requests through operator approval and later drains, plus the required no-skip MXC result.
  • Resolve maintainer decision - Resolve the maintainer decision shown above before merge.

Findings

  • [P1] Exclude requests pending before this socket opens — src/OpenClaw.SetupEngine/ApprovalRequestHelper.cs:113-134
  • [P1] Send the changed pairing scripts through WSL stdin — src/OpenClaw.SetupEngine/PairOperatorStep.cs:347-350
  • [P2] Check the pending-list result before ending the drain — src/OpenClaw.SetupEngine/VerifyEndToEndStep.cs:145-148
  • [high] Stale same-identity pairing approval — src/OpenClaw.SetupEngine/ApprovalRequestHelper.cs:113
Agent review details

Security

Needs attention: The identity-only fallback does not prove that the selected approval request belongs to the current setup socket.

Review metrics

Metric Value Why it matters
Production and test change production +228/-87, tests +290/-0, docs +6 The security-sensitive setup path changes across several owners and has substantial regression coverage.

Merge-risk options

Maintainer options:

  1. Use the maintained replacement (recommended)
    Finish the adversarial Gateway and MXC gates on the replacement before treating it as the safe landing path.
  2. Hold this branch
    Keep this PR open without merging while the replacement's final-effect proof remains incomplete.

Technical review

Best possible solution:

Land one identity-bound setup path that excludes requests pending before each socket opens, checks list results before deciding a queue is empty, preserves WSL stdin transport, and has current-head Gateway and required MXC proof.

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

Yes, at source level: current main invokes approve --latest for a missing operator request ID, and the PR's focused tests demonstrate selection among pending requests. I did not execute a live reproduction in this read-only review.

Is this the best way to solve the issue?

No. Exact request IDs are the right direction, but identity alone does not establish that a pending request belongs to the socket opened by this setup run; the replacement adds a pre-connect baseline.

Full review comments:

  • [P1] Exclude requests pending before this socket opens — src/OpenClaw.SetupEngine/ApprovalRequestHelper.cs:113-134
    The new selector accepts any unique request with the setup identity. If an older same-identity request is pending and this socket's request is delayed or absent, setup approves the older request. This concern was missed in earlier reviews of the unchanged head; capture a pre-connect baseline and reject its IDs before approval.
    Confidence: 0.96
    Late finding: first raised on code an earlier review cycle already covered.
  • [P1] Send the changed pairing scripts through WSL stdin — src/OpenClaw.SetupEngine/PairOperatorStep.cs:347-350
    The introduced pending-list and exact-approval calls use a PATH-bearing script while RunInWslAsync defaults to bash -c argv. WSL can expand $PATH before Bash receives it, breaking the pairing flow; pass inputViaStdin: true on the changed calls.
    Confidence: 0.94
  • [P2] Check the pending-list result before ending the drain — src/OpenClaw.SetupEngine/VerifyEndToEndStep.cs:145-148
    The new drain breaks when stdout or stderr merely contains 'No pending', before checking exit status or parsing JSON. A failed command or valid JSON metadata with that phrase can silently skip a real pending request; validate the result and parse structured output first.
    Confidence: 0.98

Overall correctness: patch is incorrect
Overall confidence: 0.94

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning medium; reviewed against 5a59535216ee.

Labels

Label changes:

No label changes.

Label justifications:

  • P0: Pairing approval can grant Gateway access to the wrong pending request.
  • merge-risk: 🚨 security-boundary: The new identity-only fallback can approve an older same-identity request and lacks full final-effect proof.
  • merge-risk: 🚨 compatibility: Changed WSL list and approval commands can fail on existing setups when PATH expansion alters the script.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦐 gold shrimp and patch quality is 🦪 silver shellfish.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: Authority-chain proof required: The PR body describes current-head production node approval against an official Gateway, including rejection of a foreign node and approval of the intended node. It does not show allowed, foreign, and stale final effects for operator approval and later drains through the changed WSL setup path. No stored-data contract changes. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Evidence

Security concerns:

  • [high] Stale same-identity pairing approval — src/OpenClaw.SetupEngine/ApprovalRequestHelper.cs:113
    A request from an earlier setup attempt can share the full identity and reach the final Gateway approval command when the current socket supplies no ID.
    Confidence: 0.94

What I checked:

  • Introduced selector: The new missing-ID selector matches the full identity and requires a unique match, but does not distinguish a request already pending before this setup socket opened. (src/OpenClaw.SetupEngine/ApprovalRequestHelper.cs:113, edb08328e5e0)
  • Drain result handling: The introduced drain checks for the words 'No pending' in output before checking exit status or parsing JSON, allowing an error or JSON metadata to be mistaken for an empty queue. (src/OpenClaw.SetupEngine/VerifyEndToEndStep.cs:145, edb08328e5e0)
  • WSL transport contract: The new pending-list call uses the PATH-bearing script without inputViaStdin; the command runner defaults to passing scripts through bash -c argv, which the repository documents as vulnerable to WSL variable expansion. (src/OpenClaw.SetupEngine/PairOperatorStep.cs:347, edb08328e5e0)
  • Main and release still use latest approval: Fetched main and release v2026.9.4 still call devices approve --latest in the missing-ID operator path; this PR remains relevant. (src/OpenClaw.SetupEngine/PairOperatorStep.cs:345, 5a59535216ee)
  • Maintainer replacement and proof status: Maintainer comments on this PR identify fix(setup): approve only the pairing request setup just opened #1523 as a replacement. Its provided body reports a clean merge and focused tests, while explicitly recording missing current-head adversarial final-effect Gateway proof and no-skip MXC proof.
  • Prior review continuity: The completed review of this same head retained the stdin and pending-list findings. The PR body provides real official-Gateway proof only for the node missing-ID fallback; operator approval and later drains remain unproven in that environment. (edb08328e5e0)

Likely related people:

  • shanselman: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)
  • karkarl: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)
  • Karen: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)

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 (9 earlier review cycles; latest 8 shown)
  • reviewed 2026-09-23T04:44:55.453Z sha 9604798 :: needs real behavior proof before merge. :: none
  • reviewed 2026-09-23T20:05:45.070Z sha b4008d9 :: needs real behavior proof before merge. :: [P1] [P1] Send the new pairing CLI calls through WSL stdin | [P2] [P2] Parse the pending list before declaring it empty
  • reviewed 2026-09-23T21:51:18.529Z sha b4008d9 :: needs real behavior proof before merge. :: [P1] [P1] Send the new pairing CLI calls through WSL stdin | [P2] [P2] Check the pending-list result before declaring the drain empty
  • reviewed 2026-09-23T22:30:58.482Z sha b4008d9 :: needs real behavior proof before merge. :: [P1] [P1] Send changed pairing commands through WSL stdin | [P2] [P2] Check the list result before treating the drain as empty
  • reviewed 2026-09-24T00:01:57.782Z sha b4008d9 :: needs real behavior proof before merge. :: [P1] [P1] Send the changed pairing scripts through WSL stdin | [P2] [P2] Validate the list result before declaring the drain empty
  • reviewed 2026-09-24T00:27:57.796Z sha edb0832 :: needs real behavior proof before merge. :: [P1] [P1] Send pairing approval scripts through WSL stdin | [P2] [P2] Check the list result before ending the approval drain
  • reviewed 2026-09-24T01:15:47.420Z sha edb0832 :: needs real behavior proof before merge. :: [P1] Send pairing approval scripts through WSL stdin | [P2] Check the list result before ending the approval drain
  • reviewed 2026-09-25T23:16:28.565Z sha edb0832 :: needs real behavior proof before merge. :: [P1] Send the changed pairing scripts through WSL stdin | [P2] Check the pending-list result before ending the drain

When setup uses the separate wizard identity, load that identity even if context still holds an older operator id.

Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
@shanselman

Copy link
Copy Markdown
Collaborator

Thanks, Seb. The request/device binding and the follow-up wizard-identity correction are good changes.

Reviewed head: 960479820f7e5572df9692aa986426c6c308acf0.

The end-to-end setup claim still has a bypass: after the new selector leaves an unrelated request pending, VerifyEndToEndStep.ExecuteAsync reaches the existing drains. DrainPendingDeviceApprovalsAsync still runs devices approve --latest, and the node drain approves every pending node request. The same unrelated requester can therefore be approved later in a successful setup. This is pre-existing behavior left open by the narrow fix, not a regression in your new selector.

Please remove the broad drain or limit it to the identities/request IDs captured by this setup run. Unknown pending requests should remain untouched. A full-setup regression with our intended request plus an unrelated concurrent request should prove the unrelated request is still pending at completion, not only immediately after AutoApprovePairing.

There is also a concrete integration detail with #1476 (fix(setup): keep WSL PATH scripts off the wsl.exe argv path), which I am validating first:

  • Preserve inputViaStdin: true on the new devices list --json and exact approval calls.
  • Its new PATH regression fixture currently has no OperatorDeviceId and returns the old latest-approval shape. When this PR is refreshed after that one, populate the intended device ID and a matching pending list while retaining the stdin assertions.

I want to keep these changes on your PRs and land the small fixes in a coordinated order.

@karkarl

karkarl commented Sep 23, 2026

Copy link
Copy Markdown
Collaborator

Global triage: HOLD_FOR_AUTHOR. Take confidence 35%; recommendation confidence 90%; effort moderate; risk high.

Reviewed exact head 960479820f7e. The selector correctly binds the first approval to the setup device, but the later successful path bypasses it: VerifyEndToEndStep calls DrainPendingDeviceApprovalsAsync, which repeatedly runs devices approve --latest --json, and the node drain approves every pending node request. An unrelated requester skipped by the selector can be approved moments later. Bind or remove those drains, verify the external pending-device contract against a real gateway, coordinate #1476 stdin changes, and prove under windows-wsl-gateway-e2e.

The end-to-end and node drains were still approving every pending request after the wizard selector. They now approve only the setup device request.

Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
@clawsweeper clawsweeper Bot added P0 Emergency: data loss, security bypass, crash loop, or unusable core runtime. and removed P2 Normal priority bug or improvement with limited blast radius. labels Sep 23, 2026
@shanselman shanselman added the status: 🚢 actively landing A maintainer or agent is actively driving this item through implementation, validation, or merge. label Sep 23, 2026
@shanselman

Copy link
Copy Markdown
Collaborator

Thanks, the b4008d9653b1139b633b075baff3d4ddd4767684 update removes the later --latest/approve-all drains and binds those approvals to an identity and exact request ID. That closes the path called out earlier.

There is one remaining fallback in the same setup flow: PairNodeStep.AutoApproveNodePairing still uses TryReadSinglePendingRequestId when the socket supplies no request ID. If our request is delayed or missing from the list and an unrelated node is the sole pending entry, it can still be approved.

Please use the identity-bound selector there too, against the actual full setup-node identity, with matchNodeId: true; a shortened display ID is not an authority identifier. Reject missing/ambiguous matching identity and add the “only foreign request pending” regression. Where operator and node share the same identity directory, the existing full identity can be reused rather than introducing another ownership mechanism.

This is a remaining pre-existing path, not a defect in the new bound drains. The earlier PATH/stdin integration note still applies when the relevant branches are combined.

@shanselman shanselman added status: 🚢 actively landing A maintainer or agent is actively driving this item through implementation, validation, or merge. and removed status: 🚢 actively landing A maintainer or agent is actively driving this item through implementation, validation, or merge. labels Sep 23, 2026
shanselman and others added 3 commits September 24, 2026 01:56
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 50e2dd32-b79f-4654-9231-5766c9e5316d
Reuse the existing identity-bound selector when the node socket has no request ID. Keep exact socket requests unchanged and cover foreign, missing, short, ambiguous, and unsafe requests through the actual approval path.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 50e2dd32-b79f-4654-9231-5766c9e5316d
Use an explicit review-safe synthetic credential in the new fixture; no production behavior changes.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 50e2dd32-b79f-4654-9231-5766c9e5316d
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Sep 24, 2026
@shanselman shanselman removed the status: 🚢 actively landing A maintainer or agent is actively driving this item through implementation, validation, or merge. label Sep 24, 2026
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. labels Sep 24, 2026
@SebTardif

Copy link
Copy Markdown
Contributor Author

The fallback on edb0832 selects the pending node with TrySelectPendingRequestForDevice(ctx.OperatorDeviceId, matchNodeId: true). NodeDeviceId is display-only and is not the selector. A sole foreign node fails, and a missing OperatorDeviceId fails before approve.

Local setup-engine filter AutoApproveNodePairing_WithoutRequestId: 12 passed.

@karkarl karkarl added the status: 🚢 actively landing A maintainer or agent is actively driving this item through implementation, validation, or merge. label Sep 25, 2026
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Sep 25, 2026
@karkarl

karkarl commented Sep 25, 2026

Copy link
Copy Markdown
Collaborator

Maintainer-owned replacement #1523 carries this fix on current main without rewriting the contributor fork.

It preserves the exact socket-request-ID behavior and hardens missing-ID fallback with a pre-connect request snapshot, so stale same-identity requests are excluded before uniqueness is enforced. Current replacement head: 897ed0585f6dd466614ee52d3014cc475ec933bf; rebase conflicts: none.

Local build and required Shared, Tray, SetupEngine, and 46 focused pairing tests pass. The PR records two honest blockers: no current-head live WSL Gateway proof, and no no-skip MXC run because this host is appcontainer-dacl and Crabbox is unavailable. Structured Codex autoreview is also marked blocked because the local CLI is not authenticated. No merge was performed.

@karkarl

karkarl commented Sep 26, 2026

Copy link
Copy Markdown
Collaborator

Final maintainer handoff: replacement #1523 is at 511b17680afb33de2544e9d985a7e4feb434fcf8, based on 5a59535216eea603192f2df13d4eddf1e1a20267. Original contributor head remains untouched at edb08328e5e051c30d4604ab5527e765a0ce16ad; rebase conflicts were none.

The replacement preserves exact socket request IDs and binds missing-ID fallback to one post-baseline request matching the full setup identity. Baseline and both drain parsers now check exit status and parse JSON before exact legacy empty-list fallback.

Final local validation: build passed; Shared 4,107 passed / 32 skipped; Tray 3,115 passed; SetupEngine 1,228 passed / 1 skipped; focused pairing suite 50 passed. GitHub Build and Test run 36205272379 passed on unchanged-head retry after an initial Gateway SQLite restart-intent contention failure. ClawSweeper re-reviewed 511b1768 and remains needs-human only for current-head adversarial Gateway final-effect proof and no-skip MXC proof. Rubber-duck found no remaining source blocker. Codex autoreview could not run because the local CLI is unauthenticated.

No force-push to the contributor fork and no merge were performed. Active maintainer ownership is ending; the remaining proof blockers are recorded on #1523.

@karkarl karkarl removed the status: 🚢 actively landing A maintainer or agent is actively driving this item through implementation, validation, or merge. label Sep 26, 2026
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. labels Sep 26, 2026
@shanselman

Copy link
Copy Markdown
Collaborator

Closing in favor of #1523 (fix(setup): approve only the pairing request setup just opened). The maintainer replacement preserves the exact request-ID behavior and hardens missing-ID fallback with the pre-connect request baseline and full identity matching. The original contributor branch remains untouched.

@shanselman shanselman closed this Sep 28, 2026
@SebTardif
SebTardif deleted the fix/setup-approve-opened-pairing-request branch September 28, 2026 18:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. P0 Emergency: data loss, security bypass, crash loop, or unusable core runtime. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants