Описание
vm2 Sandbox Access to Host Buffer.alloc Allows timeout Bypass Resulting in Memory Exhaustion
Summary
Sandboxed code can call Buffer.alloc() with an arbitrary size to allocate memory directly on the host heap. Because Buffer.alloc is a synchronous C++ native call, vm2's timeout option cannot interrupt it. A single request can exhaust host memory and crash the process with a FATAL ERROR: Reached heap limit.
Details
In lib/vm.js:58, Buffer is exposed to the sandbox through the HOST object. The bridge proxy (lib/bridge.js) passes Buffer.alloc() calls to the host without any size validation.
Key technical distinction from regular JavaScript memory exhaustion (e.g., while(true) a.push(...)):
- JavaScript loops: V8 can interrupt via timeout — vm2's
timeoutoption works Buffer.alloc(N): Executes as a single synchronous C++ call — V8 timeout has no opportunity to interrupt
This means:
timeout: 5000does NOT protect against this attack- A single call allocates the entire requested size at once
- In memory-constrained environments (Docker, Lambda, Kubernetes pods), this causes immediate OOM crash
Tested amplification factor: ~100 bytes HTTP request — 1,000,000:1 or greater (100 bytes request to 100MB+ host heap allocation).
PoC
Library-level PoC (Node.js script — primary):
HTTP demonstration (OOM crash):
Impact
- DoS: A single HTTP request crashes the host Node.js process via OOM. The
timeoutoption provides no protection. - Environment-dependent severity:
- Memory-constrained environments (Docker with memory limits, Kubernetes pods, Lambda): The allocation exceeds the memory limit, causing immediate process termination via OOM. This is the primary threat scenario —
FATAL ERROR: Reached heap limitwas confirmed in testing. - Unconstrained environments: The allocation succeeds and memory is reclaimed by GC after the request completes, resulting in temporary performance degradation rather than a crash.
- Memory-constrained environments (Docker with memory limits, Kubernetes pods, Lambda): The allocation exceeds the memory limit, causing immediate process termination via OOM. This is the primary threat scenario —
- Scope: All applications using vm2. Default configuration is vulnerable. Memory-constrained environments (Docker, Kubernetes, Lambda) are most severely impacted.
Пакеты
vm2
<= 3.10.5
3.11.0
Связанные уязвимости
vm2 is an open source vm/sandbox for Node.js. Prior to 3.11.0, sandboxed code can call Buffer.alloc() with an arbitrary size to allocate memory directly on the host heap. Because Buffer.alloc is a synchronous C++ native call, vm2's timeout option cannot interrupt it. A single request can exhaust host memory and crash the process with a FATAL ERROR: Reached heap limit. This vulnerability is fixed in 3.11.0.
vm2 is an open source vm/sandbox for Node.js. Prior to 3.11.0, sandboxed code can call Buffer.alloc() with an arbitrary size to allocate memory directly on the host heap. Because Buffer.alloc is a synchronous C++ native call, vm2's timeout option cannot interrupt it. A single request can exhaust host memory and crash the process with a FATAL ERROR: Reached heap limit. This vulnerability is fixed in 3.11.0.
Уязвимость функции Buffer.alloc() библиотеки vm2 пакетного менеджера NPM, позволяющая нарушителю вызвать отказ в обслуживании