Skip to main content

vm2 CVE-2026-47683

| EUVDEUVD-2026-60461 HIGH
Allocation of Resources Without Limits or Throttling (CWE-770)
2026-08-17 https://github.com/patriksimek/vm2 GHSA-gmc2-2x9w-cgh9
8.7
CVSS 4.0 · Vendor: https://github.com/patriksimek/vm2
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Submit crafted JS payload to vm2 sandbox endpoint
  2. Delivery
    Invoke Buffer.concat with attacker-controlled totalLength
  3. Exploit
    Bypass bufferAllocLimit via unwrapped host allocator path
  4. Execution
    Synchronously commit host external memory before timeout fires
  5. Persist
    Repeat calls or scale totalLength to exhaust container memory limit
  6. Impact
    Host process terminated by OOM killer

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A06:2025 - Insecure Design
ASVS 5.0
V2 - Validation and Business Logic Resource allocation limits
MITRE ATT&CK

1 technique across 1 tactic: Impact

The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up.

Exploitation Conditions

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. No special OS feature, runtime flag, or non-default Node.js configuration is required. Exploitation is bounded to availability impact only: no sandbox escape occurs, so confidentiality and integrity are unaffected. The principal limiting factor is whether sandbox code submission is reachable by an attacker - applications restricting this path to trusted internal callers face materially lower exposure.

Impact

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. The most operationally significant risk signal is the combination of a publicly available, confirmed PoC and the synchronous, timeout-immune nature of the allocation: a single sandbox call commits memory before any reactive control can act. For applications deployed with container memory limits - the environments the advisory specifically names (Docker, Kubernetes, AWS Lambda) - a single crafted request terminates the host process. The vulnerability is strictly DoS; no confidentiality or integrity impact applies, and no sandbox escape is present. Risk is meaningfully bounded by whether the application exposes vm2 sandbox execution to untrusted callers - internal or authenticated-only deployments face lower real-world exposure. EPSS data is not provided in the input; KEV listing is absent, indicating no confirmed nation-state or ransomware-actor exploitation at time of analysis, though this may change given the PoC availability and the high-value DoS class in containerized infrastructure.

Exploit ScenarioDerived

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. The publicly available PoC (embedded in GHSA-gmc2-2x9w-cgh9) demonstrates this exact pattern against vm2 3.11.3 with a 1024-byte cap configured, producing confirmed bypass output with measured RSS growth.

This Week Schedule remediation this week. Why: HIGH severity (CVSS 7.0-8.9).
Patch available 0.3% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv2 – Aug 17, 2026

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. No public exploit identified in CISA KEV at time of analysis, though functional exploit code is embedded in the GHSA advisory itself.

Earlier versions of this analysis (1)
v1 Aug 17, 2026 - 18:36

Denial-of-service via memory exhaustion in vm2 (npm) affects all versions through 3.11.5: untrusted sandbox code can bypass the embedder-configured bufferAllocLimit cap by calling Buffer.concat(list, totalLength) or Buffer.from({length: N}), causing the host Node.js process to commit arbitrarily large external memory allocations in a single synchronous C++ call that V8's timeout mechanism cannot interrupt. The bufferAllocLimit option - introduced specifically to prevent this DoS class in GHSA-6785-pvv7-mvg7 - wraps Buffer.alloc and Buffer.allocUnsafe but leaves these two allocator paths uncapped, meaning a 200-byte sandbox payload can drive hundreds of megabytes of RSS increase per call. A functional public proof-of-concept is included in the advisory; no active exploitation (CISA KEV) has been reported.

RemediationAI

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. The fix commit is available at https://github.com/patriksimek/vm2/commit/3ffb315512e634cf85c447375e85d6c83d00a4bd and the full release is at https://github.com/patriksimek/vm2/releases/tag/3.11.6. If an immediate upgrade is blocked, the only viable compensating control is to enforce a hard container or process memory ceiling - for example, Docker --memory or Kubernetes resources.limits.memory - and ensure the process restarts automatically on OOM via a supervisor or orchestrator restart policy; accept that the host process will terminate under active attack, which is a degraded-but-recoverable posture. Restricting sandbox-execution endpoints to authenticated or allowlisted callers reduces exposure surface but does not neutralize the vulnerability for any caller who retains sandbox access. Disabling bufferAllocLimit entirely is not a mitigation - doing so removes the only cap on the already-known parent vulnerability class.

Affected VersionsENISA

vm2 < 3.11.6

Affected Packages

npm vm2 fix: 3.11.6

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 1 package in npm

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

vm2 is a widely-used Node.js sandboxing library (pkg:npm/vm2) designed to execute untrusted JavaScript in isolation. The bufferAllocLimit option, introduced in 3.11.0 as a fix for GHSA-6785-pvv7-mvg7, instruments sandbox-visible Buffer constructors in lib/setup-sandbox.js with a checkBufferAllocLimit(size) guard at lines 424, 433, 474, 480, 488, 496, 504, and 510. The root cause is CWE-770 (Allocation of Resources Without Limits or Throttling): two allocation paths are never wrapped. Buffer.concat(list, totalLength) internally calls Node's Buffer.allocUnsafe(totalLength) directly on the host side, bypassing the sandbox proxy entirely. Buffer.from({length: N}) triggers Node's fromArrayLike path, which allocates a buffer of size N before filling it - no actual array of length N needs to exist, making the {length: N} object a pure synthetic trigger. Both paths reach the host V8/libuv C++ allocator with an attacker-controlled size, and neither consults localBufferAllocLimit. The allocation is synchronous and completes before V8's interrupt-based timeout can fire, meaning the memory is committed to the host's RSS regardless of any timeout setting.

Know when Docker gets its next vulnerability

  • Watch products and get an email when something new is published
  • Check this CVE against your own stack and servers
  • Exploit and PoC references, threat intelligence from 22 sources

No credit card · 7-day full trial

Severity by source

Vendor (https://github.com/patriksimek/vm2) PRIMARY 8.7 HIGH
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
vuln.today AI 7.5 HIGH

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.

3.1 AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
4.0 AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
Red Hat 7.5 HIGH

Primary rating from Vendor (https://github.com/patriksimek/vm2).

CVSS VectorVendor: https://github.com/patriksimek/vm2

Attack Vector
Network
Attack Complexity
Low
Attack Requirements
None
Privileges Required
None
User Interaction
None
Vulnerable system: Confidentiality
None
Vulnerable system: Integrity
None
Vulnerable system: Availability
High
Subsequent system: Confidentiality
None
Subsequent system: Integrity
None
Subsequent system: Availability
None

Lifecycle Timeline

3
Patch available
Aug 17, 2026 - 22:03 EUVD
CVSS changed
Aug 17, 2026 - 21:22 NVD
8.7 (HIGH)
CVE Published
Aug 17, 2026 - 17:32 cve.org
HIGH

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() at lib/setup-sandbox.js:474 and the connect(alloc, host.Buffer.alloc) at line 480.
  • allocUnsafe() at line 488 and connect(allocUnsafe, host.Buffer.allocUnsafe) at line 496.
  • allocUnsafeSlow() at line 504 and connect(allocUnsafeSlow, host.Buffer.allocUnsafeSlow) at line 510.
  • BufferHandler.apply at line 424 and BufferHandler.construct at line 433 for the deprecated Buffer(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

javascript
'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.

Blast Radius

ecosystem impact
† from your stack dependencies † transitive graph · vuln.today resolves 4-path depth
  • 22 npm packages depend on vm2 (6 direct, 16 indirect)

Ecosystem-wide dependent count for version 3.11.6.

Executive ViewAI

Why It Matters

vm2 versions 3.11.0-3.11.5 contain a critical denial-of-service vulnerability with publicly available exploit code that allows attackers to crash production services with a single 200-byte request, causing complete service unavailability through uncontrolled memory exhaustion. Organizations using vm2 to sandbox untrusted code-including SaaS platforms, code execution services, and serverless deployments-face immediate risk of infrastructure disruption and potential cascading failures across dependent systems.

Business Impact: Severe
Compensating Controls

No vendor-released patch identified at time of analysis. Interim mitigations: (1) Apply strict per-invocation memory limits via Node.js heap limits or OS-level process controls; (2) Implement rate limiting and request throttling on any endpoint invoking vm2; (3) Ensure container/pod memory limits are configured and enforced; (4) If feasible, disable or restrict use of Buffer.concat() and Buffer.from({length}) patterns within sandboxes; (5) Monitor vendor advisories daily for patch availability and plan immediate upgrade upon release.

Threat Intelligence Overview

EPSS Score
0.3%
Top 76% exploitable
Prevalence
Medium
popular Node.js sandbox library, common in code-execution platforms
Threat Intel
1
1 source
Exploit
POC
Public exploit code exists
Data Quality
7 sources
Confidence: High
EUVD NVD CVE.org EPSS Vulnrichment GHSA Vendor GitHub VulDB

How this decision was reached

The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.

SignalValue
Severity HIGH
CISA KEV No
Public POC Yes
EPSS 0.3%
Patch available Yes
Active threat No
Deciding rule
HIGH severity (CVSS 7.0-8.9)
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision
Out-of-Cycle
Exploitation
Poc
System Exposure· derived
Open
Automatable
Yes
Human Impact
Very High
Technical Impact
Total

Priority Score

64
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +44
PoC: +20
Weaponized: 0
Threat intel: 0
Gov advisory: 0

Attack Technique

Denial of Service attacks render applications or systems unavailable by overwhelming resources or triggering failure conditions.

More in Docker

View all
CVE-2024-55964 CRITICAL POC
9.8 Mar 26

An issue was discovered in Appsmith before 1.52. Rated critical severity (CVSS 9.8), this vulnerability is remotely expl

CVE-2019-5736 HIGH POC
8.6 Feb 11

runc through version 1.0-rc6 (used in Docker before 18.09.2) contains a container escape vulnerability that allows attac

CVE-2023-32077 HIGH POC
7.5 Aug 24

Netmaker makes networks with WireGuard. Rated high severity (CVSS 7.5), this vulnerability is remotely exploitable, no a

CVE-2026-39987 CRITICAL POC
9.3 Apr 08

Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/

CVE-2023-5815 HIGH POC
8.1 Nov 22

The News & Blog Designer Pack - WordPress Blog Plugin - (Blog Post Grid, Blog Post Slider, Blog Post Carousel, Blog Post

CVE-2026-66384 MEDIUM POC
5.3 Aug 12

Path traversal in JFrog Artifactory (CWE-22) enables an authenticated low-privilege user to write data outside the inten

CVE-2014-9357 CRITICAL
10.0 Dec 16

Docker 1.3.2 allows remote attackers to execute arbitrary code with root privileges via a crafted (1) image or (2) build

CVE-2026-52806 CRITICAL POC
9.9 Jun 23

Remote code execution in Gogs through 0.14.2 allows authenticated users (and unauthenticated attackers on default-config

CVE-2025-14707 HIGH POC
8.9 Dec 15

Unauthenticated remote command injection in SGWBOX N3 firmware 2.0.25 lets attackers execute arbitrary operating-system

CVE-2026-56274 HIGH POC
8.7 Jun 23

Remote code execution in Flowise before 3.1.2 allows any authenticated user (or API caller with chatflow view/update per

CVE-2026-34156 CRITICAL POC
9.9 Mar 30

Remote code execution in NocoBase Workflow Script Node (npm @nocobase/plugin-workflow-javascript) allows authenticated l

CVE-2019-15752 HIGH POC
7.8 Aug 28

Docker Desktop Community Edition before 2.1.0.1 allows local users to gain privileges by placing a Trojan horse docker-c

Vendor StatusVendor

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy