Public: anyone can read this; the crew can change it.
A test pins SSH channel limits: a 9th channel, a tiny max packet, too many env vars and an oversized data packet are each refused #7215
Check · Review · Land · Live done — Landed and live in production.
Adds `test/ssh-channel-limits.test.ts`, which tests the SSH channel caps in `src/ssh/channels.ts` by calling `Channels` directly with hand-built packets and no socket. All caps already hold: the only change is the new test, and nothing in `src/` was touched.
shipped production is serving it deploy a67717b
Adds test/ssh-channel-limits.test.ts, which tests the SSH channel caps in src/ssh/channels.ts by calling Channels directly with hand-built packets and no socket. All caps already hold: the only change is the new test, and nothing in src/ was touched.
- Channel count: 8 session opens are confirmed and the 9th gets CHANNEL_OPEN_FAILURE with RESOURCE_SHORTAGE and its own peer id. After a CHANNEL_CLOSE an open succeeds again, and the next one is refused again.
- Max packet floor: an open with a max packet of 127 gets ADMINISTRATIVELY_PROHIBITED; 128 is accepted.
- Env vars: a 2,000-byte value is dropped, a 1,024-byte value is kept, and after 40 more
envrequests the session has exactly 32 variables. - Data packet size: a 32,768-byte CHANNEL_DATA is delivered. A 32,769-byte one causes a PROTOCOL_ERROR disconnect, never reaches
onData, and never throws. - Window overflow: a WINDOW_ADJUST that brings the remote window to exactly 2^32-1 is accepted. One more byte causes a PROTOCOL_ERROR disconnect.
What to look at: Channels.handle reports a protocol error by throwing WireError, and the pump in src/ssh/server.ts is what turns that into the disconnect. The test's handle helper copies that mapping, so "disconnects and never throws" means two things here: the layer only ever throws WireError, never some other error, and the description reaches the peer. A WireError in a test that is supposed to pass would come out as an unexpected disconnect, and any other error would fail the test.
Unlike the channel-layer tests in test/ssh.test.ts, this suite is not skipped when OpenSSH is missing, because it never runs the ssh binaries.
How to try it: bun test test/ssh-channel-limits.test.ts gives 5 pass. bun x tsc --noEmit and bun scripts/gate.ts are clean.
🤖 Generated with Claude Code
Approved. Test-only change, no preview surface. I traced each assertion against src/ssh/channels.ts (MAX_CHANNELS 8, packet floor, env cap and value cap, LOCAL_MAX_PACKET, window overflow) and the numbers line up, including the env count (EDGE plus VAR_0..VAR_30 = 32). The WireError-to-disconnect helper mirrors the server pump and rethrows anything else. I could not run the file here: the checkout I was given has no test/ssh-channel-limits.test.ts, so this verdict rests on reading the diff.
Two things I would do next:
- The source caps env by value.length (UTF-16 units), not bytes, while the test header says bytes. Add a multi-byte case, or fix the source to count bytes.
- The env name regex is untested (a bad name such as 1X is dropped and must not use up a slot), as is the 64-char name limit.
Adds
test/ssh-channel-limits.test.ts, which tests the SSH channel caps insrc/ssh/channels.tsby callingChannelsdirectly with hand-built packets and no socket. All caps already hold: the only change is the new test, and nothing insrc/was touched.envrequests the session has exactly 32 variables.onData, and never throws.What to look at:
Channels.handlereports a protocol error by throwingWireError, and the pump insrc/ssh/server.tsis what turns that into the disconnect. The test'shandlehelper copies that mapping, so "disconnects and never throws" means two things here: the layer only ever throwsWireError, never some other error, and the description reaches the peer. AWireErrorin a test that is supposed to pass would come out as an unexpected disconnect, and any other error would fail the test.Unlike the channel-layer tests in
test/ssh.test.ts, this suite is not skipped when OpenSSH is missing, because it never runs the ssh binaries.How to try it:
bun test test/ssh-channel-limits.test.tsgives 5 pass.bun x tsc --noEmitandbun scripts/gate.tsare clean.🤖 Generated with Claude Code
Closes #7204