Found in safe-bash deep pentest (v3). Verified with executed PoCs against current src/ on Node 22.
Severity: High — threat (d): ~85× heap amplification on redirect-to-file; fatal OOM at 128 MB within all budgets incl. the Cloudflare profile
Summary
The v2-H5 quadratic-CPU redirect write is fixed (41.2 s → 2.6 s via amortized appendOutputBytes/appendFile), but the memory side is new: the incremental() redirect sink does, per chunk: a new Uint8Array(chunk) copy, an fs.stat atEOF probe, a shell-side appendOutputBytes doubling buffer, and fs.appendFile (which copies again). seq emits one chunk per record. Result: ~85× heap-per-output-byte and fatal OOM on a 128 MB isolate even under cloudflareWorkerLimits (3.9 MB output, inside the 4 MB maxOutputBytes cap). Bonus: on remote FS adapters (S3/WebDAV) the atEOF probe is one stat round-trip per output chunk — subrequest/billing amplification (inferred from 400k measured stat calls on memory FS; not executed against a remote adapter).
Location
packages/safe-bash/src/shell/runtime.ts:2202-2236 — incremental() sink
packages/safe-bash/src/shell/runtime.ts:2216 — per-chunk fs.stat atEOF probe
packages/safe-bash/src/shell/runtime.ts:2225 — shell-side appendOutputBytes doubling buffer
packages/safe-bash/src/shell/runtime.ts:2226 — fs.appendFile per chunk (copies again)
PoC (executed)
await shell.exec("seq 1 400000 > /work/f; wc -c < /work/f");
Measured:
- N=400000 (2.7 MB output, default limits): exit 0, 2.6 s, 400 001 appendFile + 400 002 stat calls, heap peak 228 MB (≈85× output). N=100000 → 80 MB (linear).
--max-old-space-size=128: fatal FATAL ERROR: Ineffective mark-compacts near heap limit.
- Under
cloudflareWorkerLimits: N=250000 (1.7 MB) → 119 MB peak, survives by a hair; N=550000 (3.9 MB — inside the 4 MB cap) → FATAL OOM at 128 MB with all budgets green.
Suggested fix
Cache atEOF state per descriptor after the first successful append-at-EOF (drop the per-chunk stat); batch chunks ≥64 KB before appendFile; drop the shell-side file.data duplicate for sequential descriptors.
Status: NEW (memory side of v2-H5; CPU side verified FIXED, commits #589/#591)
Found in safe-bash deep pentest (v3). Verified with executed PoCs against current
src/on Node 22.Severity: High — threat (d): ~85× heap amplification on redirect-to-file; fatal OOM at 128 MB within all budgets incl. the Cloudflare profile
Summary
The v2-H5 quadratic-CPU redirect write is fixed (41.2 s → 2.6 s via amortized
appendOutputBytes/appendFile), but the memory side is new: theincremental()redirect sink does, per chunk: anew Uint8Array(chunk)copy, anfs.statatEOF probe, a shell-sideappendOutputBytesdoubling buffer, andfs.appendFile(which copies again).seqemits one chunk per record. Result: ~85× heap-per-output-byte and fatal OOM on a 128 MB isolate even undercloudflareWorkerLimits(3.9 MB output, inside the 4 MBmaxOutputBytescap). Bonus: on remote FS adapters (S3/WebDAV) the atEOF probe is onestatround-trip per output chunk — subrequest/billing amplification (inferred from 400k measured stat calls on memory FS; not executed against a remote adapter).Location
packages/safe-bash/src/shell/runtime.ts:2202-2236—incremental()sinkpackages/safe-bash/src/shell/runtime.ts:2216— per-chunkfs.statatEOF probepackages/safe-bash/src/shell/runtime.ts:2225— shell-sideappendOutputBytesdoubling bufferpackages/safe-bash/src/shell/runtime.ts:2226—fs.appendFileper chunk (copies again)PoC (executed)
Measured:
--max-old-space-size=128: fatalFATAL ERROR: Ineffective mark-compacts near heap limit.cloudflareWorkerLimits: N=250000 (1.7 MB) → 119 MB peak, survives by a hair; N=550000 (3.9 MB — inside the 4 MB cap) → FATAL OOM at 128 MB with all budgets green.Suggested fix
Cache atEOF state per descriptor after the first successful append-at-EOF (drop the per-chunk
stat); batch chunks ≥64 KB beforeappendFile; drop the shell-sidefile.dataduplicate for sequential descriptors.Status: NEW (memory side of v2-H5; CPU side verified FIXED, commits #589/#591)