Retained state on the SSH stream path was unbounded in three places.
Stream assembly and pre-metadata buffering
- `ssh-stream-reader-memory.ts` adds two shared budgets: an aggregate assembly
ceiling (128 MiB across all in-flight streams) and a pre-metadata frame budget
(256 frames / 32 MiB). Every reader sees all stream frames and cannot filter by
streamId until its own sentinel resolves, so a foreign flood previously grew
unbounded while a reader waited.
- The per-frame oversize check is load-bearing beyond memory: without it the
eviction loop can never satisfy its exit condition on an empty buffer and spins
forever. Covered by test.
- Assembly is split into `ssh-file-stream-assembler.ts` and
`ssh-git-response-stream-assembler.ts`, both reserving from the shared budget
and releasing on every terminal path.
- Git response stream markers are validated against client-side byte and chunk
ceilings before allocation, so a relay-advertised size cannot force the
allocation directly.
Frame decoder
- An oversized frame header is now answered by retaining only the 13-byte header
and stream-discarding the advertised payload, so a malicious length field
cannot pin up to 4 GiB waiting for bytes that never arrive.
- Adversarially tiny transport fragments are coalesced pairwise, bounding the
chunk-wrapper array without copying ordinary chunks.
- Frame encode/decode route through the bounded stringify and parse helpers.
Multiplexer dispose
- Dispose handlers unsubscribe themselves while running, so iterating the live
array skipped every other handler and stranded the assembly budget of half the
in-flight streams. Detach before dispatch.
WSL hook fs bridge
- The bridge and its host adapter now pass and enforce the directory-entry and
read-byte ceilings the shared contract already declared, so a listing of an
arbitrarily large guest directory is refused at the source rather than
serialized into a multi-megabyte frame.
All new bounds are mutation-tested: reverting each one fails at least one test.
Co-authored-by: Orca <help@stably.ai>