vm2's Transformer Fast-Path Bypass Exposes Internal State Variable
Date: 2026-05
Affected: npm/vm2
Attack vector: other
Category: vulnerability-disclosure
Severity: Medium
CVE: CVE-2026-44000
CVE-2026-44003
CWE: CWE-668
CWE-693
CVSS: 5.3 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N)

### Summary vm2'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`). ### Details In `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. When the fast-path is taken: 1. **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 2. **`with` statement instrumentation is bypassed**: `with()` statements are not wrapped with `wrapWith()`, enabling scope manipulation 3. The internal state object exposes: `handleException(e)`, `wrapWith(x)`, `import(what)` While 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. ### PoC **Library-level PoC (Node.js script — primary):** ```javascript const { VM } = require("vm2"); const vm = new VM(); // Access internal state (bypassed — no catch/import/async keywords) const result = vm.run(`


Mitigations:

Architectural layers (MAESTRO):