Commit Graph
3 Commits
Author SHA1 Message Date
NeilandOrca ab04617ae7 fix(ssh): bound relay stream ingress
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>
2026-07-26 23:15:45 -07:00
NeilandOrca aab112933e Revert "fix(memory): bound OOM-prone accumulators (#10179)" (#10255)
Co-authored-by: Orca <help@stably.ai>
2026-07-23 18:35:31 -07:00
Neil 8f40ddf328 fix(memory): bound OOM-prone accumulators (#10179) 2026-07-23 06:22:56 -07:00