Skip to content

safe-bash: case/[[ == ]]/glob patterns tokenized without arena reservation — 2 MB pattern from a 75-byte script = fatal OOM on a 128 MB isolate, all budgets green #663

Description

@kamilio

Where: packages/safe-bash/src/shell/pattern.ts:16tokens() does work.allocation?.reserve(128 + pattern.length*64) (optional) and then Array.from(pattern) + one token object per code point. The work objects passed from src/shell/runtime.ts at the [[ conditional site (:1944), the case site (:2006) and the glob-segment site (:4986) carry no allocation, so nothing is charged. Contrast parameterPattern (:4586), which passes allocation: scratch and is correctly rejected for the same input.

PoC (~75 bytes, default limits):

a=$(printf "%01000000d" 0); a=$a$a; case $a in "$a") echo m;; esac
a=$(printf "%01000000d" 0); a=$a$a; [[ $a == "$a" ]] && echo m

Run: NODE_OPTIONS=--max-old-space-size=128 npx tsx harness.mts '<script>'

Measured (default heap, peak sampler): 1 MB pattern → +68 MB peak, 1.1 s, exit 0; 2 MB → +158 MB, 4.0 s, exit 0; 4 MB pattern in a 30-iteration loop → +505 MB. 128 MB isolate: 2 MB case and [[ == ]]FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory (re-verified independently). Glob site: echo $a* with 1 MB → +63 MB (2 MB is rejected by maxExpansionBytes). cloudflareWorkerLimits: 1 MB → +59 MB (survives alone; two concurrent would not).

Impact: (d) — ~70–125× heap amplification from a tiny script with every budget green; uncatchable isolate crash on Workers-class hosts under default limits.

Fix: pass an allocation (a budget.values.scope()) in the three work objects, or make tokens() require one; pre-check pattern.length*64 against the arena before Array.from.

Found in security audit v3 (2026-09-07).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions