Public: anyone can read this; the crew can change it.

A test pins SSH auth limits: the 7th signed attempt and the 33rd unsigned probe each disconnect, and nothing is authorised #7205

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

I added `test/ssh-auth-limits.test.ts`, which pins both SSH auth caps, and pushed it. The new tests pass and `tsc --noEmit` is clean. I ran only this file, not the full suite. Neither limit was off by one, so `src/ssh/auth.ts` is unchanged.

shipped production is serving it deploy ef63cd6

opened this

I added test/ssh-auth-limits.test.ts, which pins both SSH auth caps, and pushed it. The new tests pass and tsc --noEmit is clean. I ran only this file, not the full suite. Neither limit was off by one, so src/ssh/auth.ts is unchanged.

The test drives Auth directly through a fake AuthHost that records send, disconnect and succeeded. It needs no socket and no OpenSSH, and the file runs in about 250 ms.

  • Signed cap: six bad-signature requests each get USERAUTH_FAILURE. The seventh disconnects with "too many authentication attempts", sends nothing more, and succeeded is never called.
  • Probe cap: 32 unsigned probes for a key authorize refuses each get FAILURE. The 33rd disconnects with "too many public key probes".
  • Separate budgets: after 20 probes, a valid signed request still gets USERAUTH_SUCCESS.
  • maxAttempts override: with maxAttempts set to 2, the third signed request disconnects, even though it carries a valid signature. With it set to 10, the eleventh disconnects.

I did not test the cap with non-ed25519 key types. Every request uses an ed25519 key.

To try it: bun test test/ssh-auth-limits.test.ts.

🤖 Generated with Claude Code

Closes #7202

Approved

Clean. This pull adds tests only: src/ is untouched, and it adds no dependency, socket, or shell call. I ran the file at head 7691ac2 against the real src/ssh/auth.ts: 4 pass, 23 expects, about 250 ms. I also checked that the tests catch the bugs they claim to. Each of these mutations of auth.ts fails exactly the test meant for it:

  • DEFAULT_MAX_ATTEMPTS 6→7 fails the 7th-attempt test.
  • MAX_QUERIES 32→33 fails the 33rd-probe test.
  • Counting probes against the signed budget fails the separate-budgets test.

The maxAttempts=2 case sends a valid signature as the third request. That proves the cap is checked before the signature is verified, which is the property that matters against brute force. The preview answers 200, and a test-only change has nothing new to show there.

Two small points. Neither blocks this pull; fold them in if you touch the file again.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs