fix(ssh): stop readiness on host-key rejection - #1877
Conversation
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review blockedAutomated review did not run, so no review verdict was produced. Reason: The input-safety check rejected material in this revision. No detected value, path, or scanner output is reproduced here. ClawSweeper will not retry this unchanged revision. Next step: If this is a genuine credential, remove and rotate it. If it is an intentional test fixture, a maintainer must review and qualify it. |
|
Codex review: needs real behavior proof before merge. Reviewed September 5, 2026, 5:50 AM ET / 09:50 UTC. ClawSweeper reviewWhat this changesThe CLI captures bounded SSH diagnostics and stops readiness waits on detected host-key rejection, with regression tests and troubleshooting guidance. Regression provenancePossible regression — suspected (reviewed change). No predecessor PR is attributed. Merge readiness⛔ Blocked before merge - 5 items remain This remains useful work: main and v0.49.1 still discard the diagnostic, and the linked provider fix addresses a different problem. Two introduced regressions prevent approval. Priority: P2 Review scores
Verification
How this fits togetherCrabbox checks a runner’s SSH connection and toolchain before syncing files or executing commands. Provider-supplied targets select direct, proxy, or WSL readiness probes. flowchart TD
A[Runner connection details] --> C[SSH readiness probes]
B[Existing host trust] --> C
C --> D{Probe result}
D -->|Ready| E[Sync or execute]
D -->|Host-key rejection| F[Stop with diagnostic]
D -->|Startup pending| G[Bounded wait]
G --> C
Before merge
Findings
Agent review detailsSecurityNone. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Stop genuine client host-key failures promptly while preserving verified fallback selection and retryable remote checks, with compatibility coverage for existing multi-port configurations. Do we have a high-confidence way to reproduce the issue? Yes, from source: a rejected primary exits before a valid fallback, and a trusted remote readiness command returning 255 with the matching stderr text is misclassified. These scenarios were not executed during this read-only review. Is this the best way to solve the issue? No, not as written: the narrow repair should distinguish local SSH rejection from remote command failure and preserve the established candidate-selection contract. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against add89881ae9b. LabelsLabel changes:
Label justifications:
EvidenceWhat I checked:
Likely related people:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
|
Keep diagnostics bounded without losing matches across write boundaries or large stderr, and stop WSL SFTP fallback after host-key rejection. Co-authored-by: Shun Kakinoki <shunkakinoki@gmail.com>
Co-authored-by: Shun Kakinoki <shunkakinoki@gmail.com>
SSH readiness currently treats a rejected host key as an ordinary startup delay, discards the diagnostic, and repeats until the readiness deadline. Stop on the first host-key verification failure with a sanitized explanation and guidance to verify the lease identity and host trust.
The change covers direct, proxy, and WSL readiness paths. The detector retains only fixed-size streaming match state, not diagnostic text, so split writes and output beyond 64 KiB cannot erase a rejection. The returned readiness explanation remains sanitized, while the original exit cause is retained. Authentication startup failures, connection failures, toolchain readiness, cancellation, and workspace-owner failures retain their existing behavior. No host keys are removed and verification is never weakened.
This complements the provider trust-isolation fix in #1785 and the incident in #1748. It does not replace that fix: new leases still need the correct trust scope. This PR changes only failure handling and diagnosis, with no provider configuration or credential changes.
Validation used the repository's Go 1.26.5 toolchain:
go test -race ./internal/cli -run 'Test(WaitForSSHReady|SSHReadiness|ResolveSSHPortNoInput|ProxySSHReadiness|WSL2Readiness)' -count=1 -timeout=2mgo test -race ./internal/providers/asciibox -count=1 -timeout=2mgo vet ./internal/cli ./internal/providers/asciiboxgo build -trimpath -o <isolated-output> ./cmd/crabboxgit diff --checkThe full repository suite and a new paid-provider lifecycle were not run. The local executable was built for verification only; this does not update fleet installations.
Maintainer follow-up and current proof
The original fix is preserved, with two gaps repaired: host-key rejection during WSL's separate SFTP connection now stops before port fallback, and streaming detection survives arbitrary write boundaries and oversized stderr without changing the existing bounded-buffer truncation contract. Three overflow cases and two WSL SFTP cases failed on the submitted head before these additions; the split-write and no-phrase controls passed.
On integrated head
1621a5d1525b0f00f1c5e631afe6d61162ab8509, the related CLI race suite passed in 44.542 seconds with no skips, including both real OpenSSH loopback cases and byte-identical known-hosts checks:The proxy test exercises the proxy routing branch against the owned local server, not a hosted provider gateway. WSL coverage uses the existing synthetic SSH recorder and in-process SFTP fixtures; native Windows is not claimed. No raw stderr/key text is retained by the detector, no account SSH keys or provider resources were used, and no trust checks were relaxed.
Managed Codex review is P0 scoped-clean. The SSH documentation and Unreleased entry are maintainer-added landing work; contributor credit remains with @shunkakinoki. Published release-note sections are unchanged.
Landing verification
All applicable exact-head workflows passed: CI, Release Check, Connector E2E Smokes, and Docs UI Proof. The full repository suite was not run locally; this CI result is separate from the focused local proof above. CodeQL default setup does not analyze fork pull requests, so no CodeQL result is claimed here.
The optional bot review produced no current-head verdict: its input-safety classification stopped on pre-existing test content. That input remains blocked and no scanner policy or fixture qualification was changed. The independent managed scan/review and maintainer inspection above are separate evidence, not a qualification of the bot's input. Landing uses the ordinary maintainer merge path with GitHub protections intact, not bot automerge or an administrative override.