Severity by source
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Network vector with no privilege requirement, as applications exposing vm2 sandboxes typically accept untrusted code without authentication; impact is availability-only with unchanged scope since no sandbox escape occurs.
Primary rating from Vendor (https://github.com/patriksimek/vm2).
CVSS VectorVendor: https://github.com/patriksimek/vm2
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Lifecycle Timeline
7Blast Radius
ecosystem impact- 4,224 npm packages depend on vm2 (1,156 direct, 3,100 indirect)
Ecosystem-wide dependent count for version 3.11.6.
DescriptionCVE.org
Summary
vm2 bufferAllocLimit cap bypassed by Buffer.concat and Buffer.from arrayLike
The bufferAllocLimit option introduced in 3.11.0 (GHSA-6785-pvv7-mvg7) caps host-side Buffer allocations driven by sandbox code, the way embedders opt into timeout. The cap wraps Buffer.alloc, Buffer.allocUnsafe, Buffer.allocUnsafeSlow, and the deprecated Buffer(N) / new Buffer(N) forms. Two other API paths reach the same host C++ allocator with an attacker-controlled size and are not capped: Buffer.concat(list, totalLength) and Buffer.from(arrayLike) with a fake length. Sandbox code can use either to allocate an arbitrary number of host external bytes in a single call, defeating the explicit DoS mitigation the embedder configured.
Details
lib/setup-sandbox.js installs checkBufferAllocLimit at every wrapped entry to host Buffer allocation:
alloc()atlib/setup-sandbox.js:474and theconnect(alloc, host.Buffer.alloc)at line 480.allocUnsafe()at line 488 andconnect(allocUnsafe, host.Buffer.allocUnsafe)at line 496.allocUnsafeSlow()at line 504 andconnect(allocUnsafeSlow, host.Buffer.allocUnsafeSlow)at line 510.BufferHandler.applyat line 424 andBufferHandler.constructat line 433 for the deprecatedBuffer(N)/new Buffer(N)numeric-first-arg paths.
Buffer.concat is not wrapped. The sandbox-visible Buffer.concat is therefore the bridge proxy of the host Buffer.concat, which calls into Node's Buffer.allocUnsafe(totalLength) internally without going through the sandbox-side allocUnsafe wrapper. Same for Buffer.from when the argument is array-like ({length: N}): Node's fromArrayLike allocates a buffer of size N before the iteration that fills it. Neither of those allocator paths consult localBufferAllocLimit.
The mitigation rationale documented in docs/ATTACKS.md Category 23 explicitly enumerates the surfaces that were considered and either capped (Buffer.alloc family) or punted to follow-up (new Uint8Array(N), new ArrayBuffer(N), String.prototype.repeat). Buffer.concat(list, totalLength) is not listed in either group, and Buffer.from(arrayLike) is mentioned only as "bounded by source array size which had to be allocated through some other path first" -- which is not true for the {length: N} form, because no array of length N actually exists.
A single call from sandbox to Buffer.concat([Buffer.from('a')], 50 * 1024 * 1024) allocates 50 MiB of host external memory. The allocation itself is a single synchronous host C++ call that timeout cannot interrupt, exactly like the original advisory. The zero-fill that follows is interruptible, but the memory is already committed by the time the interrupt could fire, so the embedder's container memory budget is the only ceiling. The same pattern in a loop, or with a larger totalLength, drives RSS up by hundreds of megabytes per call.
The fix uses the existing checkBufferAllocLimit(size) helper and a sandbox-side wrapper installed via connect(...) -- one for Buffer.concat that sums the totalLength (or falls back to summing list lengths) and one for Buffer.from that recognises the array-like-with-numeric-length branch.
PoC
'use strict';
const { VM, NodeVM } = require('vm2');
function ext() { return Math.round(process.memoryUsage().external / 1024 / 1024); }
function tryBypass(label, code) {
const ext0 = ext();
let buf;
try { buf = code(); }
catch (e) {
console.log(`[${label}] CAPPED -- ${String(e).split('\n')[0]}`);
return;
}
console.log(`[${label}] BYPASSED -- got ${buf && buf.length} bytes (external +${ext() - ext0} MB)`);
}
console.log('Cap is configured at 1024 bytes.\n');
const vm1 = new VM({ bufferAllocLimit: 1024 });
tryBypass('VM Buffer.alloc(50MB) ',
() => vm1.run('Buffer.alloc(50 * 1024 * 1024)'));
const vm2 = new VM({ bufferAllocLimit: 1024 });
tryBypass('VM Buffer.concat 50MB ',
() => vm2.run('Buffer.concat([Buffer.from("a")], 50 * 1024 * 1024)'));
const vm3 = new NodeVM({ bufferAllocLimit: 1024 });
tryBypass('NodeVM Buffer.concat 50MB ',
() => vm3.run('module.exports = Buffer.concat([Buffer.from("a")], 50 * 1024 * 1024);'));
const vm4 = new VM({ bufferAllocLimit: 1024 });
tryBypass('VM Buffer.from({length: 8MB})',
() => vm4.run('Buffer.from({length: 8 * 1024 * 1024})'));Run with node poc.js against vm2@3.11.3:
Cap is configured at 1024 bytes.
[VM Buffer.alloc(50MB) ] CAPPED -- RangeError: Buffer allocation size 52428800 exceeds bufferAllocLimit 1024
[VM Buffer.concat 50MB ] BYPASSED -- got 52428800 bytes (external +50 MB)
[NodeVM Buffer.concat 50MB ] BYPASSED -- got 52428800 bytes (external +50 MB)
[VM Buffer.from({length: 8MB})] BYPASSED -- got 8388608 bytes (external +8 MB)Process RSS climbs by the same amount each call, confirming a real host C++ allocation rather than a sandbox-realm-only effect.
Impact
This is the same DoS class GHSA-6785-pvv7-mvg7 was filed for: untrusted sandbox code amplifying a small payload into a large synchronous host external-memory allocation that V8's timeout cannot preempt. In the environments the advisory cites -- Docker memory limits, Kubernetes pods, AWS Lambda -- a single 200-byte sandbox payload can drive a multi-hundred-megabyte RSS jump and OOM the host process.
The Category 23 fix was specifically scoped to "cap host Buffer external allocation" and embedders are documented to opt into bufferAllocLimit as their layered defense against this class. The two paths above are uncapped, so an embedder that has configured bufferAllocLimit: 32 * 1024 * 1024 (the value recommended in the README's Hardening recommendations) is still vulnerable to the exact attack the option was designed to prevent. The mitigation invariant -- "every Buffer external allocation driven by sandbox code is capped by bufferAllocLimit" -- does not hold.
No sandbox escape; pure DoS.
Articles & Coverage 1
AnalysisAI
Denial-of-service in vm2 (Node.js sandbox library) versions 3.11.0-3.11.5 allows sandbox code to bypass the bufferAllocLimit DoS mitigation via two unwrapped allocation paths - Buffer.concat(list, totalLength) and Buffer.from({length: N}) - committing unbounded host external memory in a single synchronous C++ call that V8's timeout mechanism cannot interrupt. A publicly available PoC confirms that a 200-byte sandbox payload inflates host RSS by hundreds of megabytes per invocation, making a single crafted request sufficient to OOM-kill a host process running inside a Docker container, Kubernetes pod, or AWS Lambda function. …
Unlock full vulnerability intelligence
- Risk assessment & exploitation conditions
- Attack chain visualization
- Remediation with exact patch versions
- Threat intelligence from 22 sources
- Personal watchlist & email alerts
Free forever · No credit card required
Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata
Vulnerability AssessmentAI
| Exploitation | Exploitation requires three concrete conditions: (1) the target application runs vm2 version 3.11.0-3.11.5 with the `bufferAllocLimit` option set - applications without `bufferAllocLimit` are already subject to the parent advisory GHSA-6785-pvv7-mvg7; (2) the attacker can execute arbitrary JavaScript code inside the vm2 sandbox, typically via an API endpoint or service that accepts user-provided code strings; and (3) the host process is subject to a finite memory budget (container limit, Lambda memory cap) that can be exhausted. … Additional conditions and limiting factors are described in the full assessment. |
| Risk Assessment | The CVSS 4.0 score of 8.7 (AV:N/AC:L/AT:N/PR:N/UI:N/VA:H) accurately reflects high availability impact with no complexity or privilege barrier. … Full risk analysis with EPSS, KEV, and SSVC signal comparison available after sign-in. |
| Exploit Scenario | An attacker submits a 200-byte JavaScript payload to an application endpoint that evaluates user-supplied code in a vm2 sandbox: `Buffer.concat([Buffer.from('a')], 500 * 1024 * 1024)`. The call bypasses the configured `bufferAllocLimit` and commits 500 MiB of host external memory synchronously - before V8's timeout interrupt fires - causing the container's memory limit to be breached and the host process to be OOM-killed. … |
| Remediation | Upgrade to vm2 3.11.6 immediately; this release installs sandbox-side wrappers via `connect(...)` for `Buffer.concat`, `Buffer.from`, and `Buffer.copyBytesFrom` that consult `localBufferAllocLimit` before delegating to the host allocator, restoring the intended invariant. … Detailed patch versions, workarounds, and compensating controls in full report. |
Recommended ActionAI
Within 24 hours, enumerate all systems running vm2 versions 3.11.0-3.11.5 and assess their exposure (determine whether they execute untrusted/user-supplied code). …
Sign in for detailed remediation steps and compensating controls.
Threat intelligence, references, and detailed analysis are available after sign-in.
More in Kubernetes
View allA critical vulnerability in Kubernetes ingress-nginx controller allows unauthenticated attackers with pod network access
Credential-harvesting malware compromised 84 versions of 42 TanStack npm packages on 2026-05-11 via chained GitHub Actio
Kubernetes ingress-nginx contains a configuration injection vulnerability via the mirror-target and mirror-host Ingress
A security issue was discovered in ingress-nginx https://github.com/kubernetes/ingress-nginx where the `auth-url` Ingres
A security issue was discovered in ingress-nginx https://github.com/kubernetes/ingress-nginx where the `auth-tls-match-c
Kubernetes API server in all versions allow an attacker who is able to create a ClusterIP service and set the spec.exter
A security issue was discovered in Kubernetes where a user that can create pods on Windows nodes may be able to escalate
Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes. Rated critical severity (CVSS 9.9), this vulne
Unauthenticated remote attackers can trigger complete database overwrites, server-side file reads, and SSRF attacks agai
The Kubernetes integration in GitLab Enterprise Edition 11.x before 11.2.8, 11.3.x before 11.3.9, and 11.4.x before 11.4
Fluentd configuration injection in the kube-logging Logging operator before 6.6.0 allows a namespace-scoped user who can
Kyverno Kubernetes policy engine prior to 1.x has a privilege escalation vulnerability (CVSS 9.9) allowing policy bypass
Same technique Denial Of Service
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-60461
GHSA-gmc2-2x9w-cgh9