Skip to content

[Bug]: auto-repair stale .pub instead of skipping when it doesn't pair with local .priv #3396

@la14-1

Description

@la14-1

What happened?

Follow-up to #3395. That PR catches the silent-failure mode where ~/.ssh/id_ed25519.pub on disk doesn't pair with ~/.ssh/id_ed25519 (stale pub copied from another machine, etc.) — but only diagnoses it: the bad pair is filtered out and the user is told to fix it manually.

Real-world report from Slack: user hit SSH key 'id_ed25519' already registered with DigitalOcean followed by 33× Permission denied (publickey) on a hermes launch. With #3395 merged, they'd instead see a "skipped — does not pair" warning and then have to manually run ssh-keygen -y -P "" -f ~/.ssh/id_ed25519 > ~/.ssh/id_ed25519.pub to recover.

Proposed fix

In discoverSshKeys() (or a new helper), when verifyKeyPair() returns "mismatch":

  1. Rename the stale .pub to .pub.spawn-backup-<timestamp> (never destroy user data).
  2. Write the correct pub — derived from the priv via ssh-keygen -y -P "" -f <priv> — to <priv>.pub.
  3. Log: Repaired ~/.ssh/id_ed25519.pub (stale public key replaced; original saved as .pub.spawn-backup-*).
  4. Continue with the repaired pair — SSH handshake will now succeed because the pub registered with the cloud provider actually pairs with the local priv.

The .priv is authoritative; any .pub on disk that doesn't derive from it is wrong by definition, so the rewrite is safe. Passphrase-protected keys (verifyKeyPair === "unverifiable") continue to be skipped silently — we can't derive the pub for those without the passphrase.

Acceptance criteria

  • Mismatched .pub is auto-rewritten from the matching .priv
  • Original .pub is preserved at <priv>.pub.spawn-backup-<timestamp>
  • Passphrase-protected keys are still skipped silently (unchanged behavior)
  • Tests cover: successful repair + backup created, passphrase case still skipped, repair survives across cached discoverSshKeys() calls
  • Slack user's failure reproduces as a passing e2e test (can stage a bad .pub)

References

Filed from Slack by SPA

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpending-reviewIssue awaiting initial review

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions