{"description":"Trending threats, MITRE ATT\u0026CK coverage, and detection metadata — refreshed continuously.","feed_url":"https://feed.craftedsignal.io/products/vm2--3.10.5/","home_page_url":"https://feed.craftedsignal.io/","items":[{"_cs_actors":[],"_cs_cves":[],"_cs_exploited":false,"_cs_products":["vm2 (\u003c= 3.10.5)"],"_cs_severities":["high"],"_cs_tags":["sandbox-escape","dos","memory-exhaustion","vm2"],"_cs_type":"advisory","_cs_vendors":["npm"],"content_html":"\u003cp\u003eThe vm2 npm package, a sandbox environment for executing untrusted JavaScript code, is susceptible to a denial-of-service attack.  Specifically, versions 3.10.5 and earlier allow sandboxed code to bypass the configured timeout by calling \u003ccode\u003eBuffer.alloc()\u003c/code\u003e with a large, attacker-controlled size. Because \u003ccode\u003eBuffer.alloc\u003c/code\u003e is a synchronous C++ native call, vm2\u0026rsquo;s \u003ccode\u003etimeout\u003c/code\u003e option cannot interrupt it.  This bypass enables a malicious actor to exhaust the host system\u0026rsquo;s memory, leading to a crash. This is particularly impactful in memory-constrained environments like Docker containers, Kubernetes pods, and serverless functions (e.g., AWS Lambda), where a single request can trigger an out-of-memory (OOM) error, resulting in service disruption. The amplification factor can be significant, with a small HTTP request (e.g., 100 bytes) triggering a large memory allocation (e.g., 100MB+).\u003c/p\u003e\n\u003ch2 id=\"attack-chain\"\u003eAttack Chain\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003eAn attacker sends a malicious HTTP request to an application using vm2.\u003c/li\u003e\n\u003cli\u003eThe request contains JavaScript code intended for execution within the vm2 sandbox via an API endpoint (e.g. \u003ccode\u003e/api/execute\u003c/code\u003e).\u003c/li\u003e\n\u003cli\u003eThe malicious JavaScript code leverages \u003ccode\u003eBuffer.alloc()\u003c/code\u003e with a large size (e.g., \u003ccode\u003eBuffer.alloc(1024*1024*100)\u003c/code\u003e).\u003c/li\u003e\n\u003cli\u003eThe \u003ccode\u003eBuffer.alloc()\u003c/code\u003e call is proxied to the host environment through the bridge proxy in \u003ccode\u003elib/bridge.js\u003c/code\u003e without size validation.\u003c/li\u003e\n\u003cli\u003eThe host system attempts to allocate the requested memory synchronously.\u003c/li\u003e\n\u003cli\u003eIn memory-constrained environments, the allocation exceeds available resources.\u003c/li\u003e\n\u003cli\u003eThe Node.js process crashes with a \u003ccode\u003eFATAL ERROR: Reached heap limit\u003c/code\u003e due to JavaScript heap exhaustion.\u003c/li\u003e\n\u003cli\u003eThe application becomes unavailable, resulting in a denial-of-service condition.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"impact\"\u003eImpact\u003c/h2\u003e\n\u003cp\u003eThis vulnerability allows for denial-of-service (DoS) attacks. A single HTTP request containing malicious JavaScript code can crash the host Node.js process by exhausting its memory. The severity of the impact depends on the environment.  In memory-constrained environments such as Docker containers or Kubernetes pods, the attack causes immediate process termination. Even in unconstrained environments where the memory allocation might succeed and be reclaimed, the attack can cause temporary performance degradation. The vulnerability affects all applications using vm2 version 3.10.5 or earlier in its default configuration.\u003c/p\u003e\n\u003ch2 id=\"recommendation\"\u003eRecommendation\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eUpgrade to a patched version of the \u003ccode\u003evm2\u003c/code\u003e package that addresses this vulnerability.\u003c/li\u003e\n\u003cli\u003eApply rate limiting to the API endpoints that execute code within the vm2 sandbox to mitigate the impact of potential attacks.\u003c/li\u003e\n\u003cli\u003eMonitor application logs for \u003ccode\u003eFATAL ERROR: Reached heap limit\u003c/code\u003e messages, which may indicate exploitation attempts.\u003c/li\u003e\n\u003cli\u003eDeploy the Sigma rule to detect suspicious calls to Buffer.alloc with unusually large sizes.\u003c/li\u003e\n\u003cli\u003eImplement resource limits (e.g., memory limits) for processes running vm2 to prevent complete system exhaustion.\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-05-07T04:26:39Z","date_published":"2026-05-07T04:26:39Z","id":"/briefs/2024-01-03-vm2-buffer-alloc-dos/","summary":"A vulnerability exists in the vm2 npm package (\u003c= 3.10.5) where sandboxed code can bypass the timeout protection by calling Buffer.alloc() with an arbitrary size, leading to memory exhaustion on the host system.","title":"vm2 Sandbox Escape via Buffer.alloc Memory Exhaustion","url":"https://feed.craftedsignal.io/briefs/2024-01-03-vm2-buffer-alloc-dos/"},{"_cs_actors":[],"_cs_cves":[{"cvss":9.8,"id":"CVE-2026-22709"}],"_cs_exploited":false,"_cs_products":["vm2 (\u003c= 3.10.5)"],"_cs_severities":["high"],"_cs_tags":["vm2","sandbox-escape","denial-of-service","nodejs"],"_cs_type":"advisory","_cs_vendors":["npm"],"content_html":"\u003cp\u003eA sandbox escape vulnerability has been identified in vm2 versions 3.10.5 and earlier. This vulnerability enables malicious sandboxed code to crash the host Node.js process through a crafted \u003ccode\u003ePromise\u003c/code\u003e constructor that triggers an unhandled rejection. The root cause lies in the fact that Promise executor errors are not adequately caught and sanitized before they can propagate as unhandled rejections to the host process. This results in an immediate process crash, effectively causing a denial-of-service condition. Notably, the \u003ccode\u003eallowAsync: false\u003c/code\u003e setting, intended to mitigate asynchronous code execution, does not prevent this vulnerability and, paradoxically, can exacerbate the issue by blocking \u003ccode\u003e.catch()\u003c/code\u003e handlers, thereby guaranteeing that rejections remain unhandled. The CVE-2026-22709 patch (v3.10.2) only sanitized \u003ccode\u003e.then()\u003c/code\u003e and \u003ccode\u003e.catch()\u003c/code\u003e callback chains but left the executor-to-unhandledRejection path completely open.\u003c/p\u003e\n\u003ch2 id=\"attack-chain\"\u003eAttack Chain\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003eAttacker crafts malicious JavaScript code designed to be executed within a vm2 sandbox.\u003c/li\u003e\n\u003cli\u003eThe malicious code constructs a \u003ccode\u003ePromise\u003c/code\u003e object using the \u003ccode\u003ePromise\u003c/code\u003e constructor.\u003c/li\u003e\n\u003cli\u003eWithin the \u003ccode\u003ePromise\u003c/code\u003e executor function, an \u003ccode\u003eError\u003c/code\u003e object is created.\u003c/li\u003e\n\u003cli\u003eThe \u003ccode\u003eError\u003c/code\u003e object\u0026rsquo;s \u003ccode\u003ename\u003c/code\u003e property is set to a \u003ccode\u003eSymbol()\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eThe code then attempts to access the \u003ccode\u003estack\u003c/code\u003e property of the \u003ccode\u003eError\u003c/code\u003e object, triggering V8\u0026rsquo;s internal \u003ccode\u003eFormatStackTrace\u003c/code\u003e function.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eFormatStackTrace\u003c/code\u003e attempts \u003ccode\u003eSymbol.toString()\u003c/code\u003e, resulting in a host-realm \u003ccode\u003eTypeError\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eBecause no \u003ccode\u003e.catch()\u003c/code\u003e handler is attached, the error becomes an unhandled rejection.\u003c/li\u003e\n\u003cli\u003eThe unhandled rejection propagates to the host Node.js process, causing it to crash.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"impact\"\u003eImpact\u003c/h2\u003e\n\u003cp\u003eSuccessful exploitation of this vulnerability leads to a denial-of-service (DoS) condition. A single malicious request can crash the entire host Node.js process, disrupting service for all concurrent users. The persistent nature of this DoS, coupled with the ease of triggering it, renders the application unavailable even with standard recovery mechanisms like Docker restart policies or Kubernetes liveness probes. The attacker only needs to send a small request (approximately 150 bytes) to bring down the entire server, demonstrating a high amplification factor. All applications using vm2 are vulnerable, regardless of the \u003ccode\u003eallowAsync\u003c/code\u003e setting.\u003c/p\u003e\n\u003ch2 id=\"recommendation\"\u003eRecommendation\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eUpgrade to a patched version of vm2 that addresses this vulnerability. As of this writing, no patched version exists, but monitor the project for updates.\u003c/li\u003e\n\u003cli\u003eImplement rate limiting on API endpoints that execute user-provided JavaScript code to reduce the impact of DoS attacks.\u003c/li\u003e\n\u003cli\u003eDeploy the Sigma rule \u0026ldquo;Detect vm2 Sandbox Escape Attempt via Symbol Error Name\u0026rdquo; to identify attempts to exploit this vulnerability within your environment.\u003c/li\u003e\n\u003cli\u003eMonitor application logs for unhandled promise rejections, which could indicate exploitation attempts.\u003c/li\u003e\n\u003cli\u003eConsider implementing a custom error handler within the vm2 sandbox to catch and sanitize errors before they can propagate to the host process.\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2024-01-03T12:00:00Z","date_published":"2024-01-03T12:00:00Z","id":"/briefs/2024-01-vm2-sandbox-escape/","summary":"A sandbox escape vulnerability exists in vm2 versions 3.10.5 and earlier that allows sandboxed code to crash the host Node.js process via a Promise constructor that triggers an unhandled rejection, leading to a denial-of-service condition.","title":"vm2 Sandbox Escape via Promise Constructor Unhandled Rejection","url":"https://feed.craftedsignal.io/briefs/2024-01-vm2-sandbox-escape/"}],"language":"en","title":"CraftedSignal Threat Feed — Vm2 (\u003c= 3.10.5)","version":"https://jsonfeed.org/version/1.1"}