A general audit of the code, and what it turned up.
No live vulnerability was found. The critical paths — AEAD authenticate-then-decrypt, the low-order point check and signature verification in the key exchange, bounds checks before every allocation, the host key check across a rekey — all hold.
Five findings, all now fixed:
- One byte comparison instead of four (#54). Two were constant-time and two were not, with nothing at a call site to say which. Not exploitable, since the early-exit pair compared public host keys, but the next thing needing comparison might be a tag.
- The server's banner is shown (#55). It was being read and dropped, so a notice about an expiring password or an environment you had landed on went nowhere.
- Leaving says so (#56). The client now sends SSH_MSG_DISCONNECT instead of dropping the socket, so a user who chose Disconnect no longer looks to the server like a handset that fell off the network.
- A bridge catalogue you backed out of stays gone (#57). It used to arrive seconds later and take over the screen.
- Less duplication and less dead code (#58). Three copies of the same line reader became one, and Profile's convenience constructors — one of which had already caused a bug by dropping a field — are gone.
230 offline vectors and 41 against a live OpenSSH.