CVE-2023-29199 - Breaking Out of the vm2 Sandbox—Explained Simply

The world of JavaScript sandboxing took a serious hit on April 10, 2023, when CVE-2023-29199 was announced. This vulnerability impacted vm2, a popular Node.js library used to safely execute untrusted code. Hackers could abuse a flaw in the “exception sanitization logic” to break out of the sandbox and run any code they want on the host machine. If you use vm2 (up to v3.9.15), read on—this vulnerability could pose a real threat to your apps and servers.

What's the Big Deal About vm2?

vm2 is one of the most popular modules allowing Node.js apps to run untrusted code in a "safe" environment. It's used everywhere from online code editors to plug-in systems and scientific computing tools.

The idea: If someone submits nasty JavaScript code, put it in the vm2 sandbox and it can't escape to mess with your real system.

What Was the Vulnerability? (CVE-2023-29199 Explained)

The problem was in the core of how vm2 handles exceptions (errors) thrown by code running in the sandbox. Normally, vm2 sanitizes any exception the sandbox might throw—meaning, it strips out sensitive information and makes sure no host reference is available to the untrusted script.

But before version 3.9.16, vm2 had a flaw in its source code transformer logic. This let an attacker bypass the handleException() mechanism and cause the host to leak unsanitized exceptions into the sandbox. This leak could give away keys to the kingdom: real error objects, stack traces, and even references back to actual objects on your Node.js server.

Exploit Possibility

A skilled attacker could craft some evil code to recreate host objects—and from there, by using prototype pollution or other tricks, escape the sandbox entirely. The end result? Arbitrary code execution on your host environment, as if the attacker was running node mycode.js on your server. That’s bad.

Demo: Proof-of-Concept (PoC)

Let’s see how this could look in real code (WARNING: This is for educational purposes! Don't use this on live systems):

const { NodeVM } = require('vm2');

const evilScript = `
  // Try to access internal host references
  try {
    (function() {
      throw new Error("Break sandbox");
    })();
  } catch (e) {
    // In affected versions, e may leak a live host exception object
    // Exploiter can get access to host's prototype and functions
    process.mainModule.require('child_process').execSync('id'); // Remote Code Execution!
  }
`;

const vm = new NodeVM({
  sandbox: {},
  require: {
    external: true,
    builtin: ['child_process'],
  }
});

try {
  vm.run(evilScript);
} catch (error) {
  // Exception handling, but attacker code may already have run!
}

In vulnerable versions, that evilScript could potentially escape and run commands on your server.

Technical Breakdown

1. Exception Sanitization Failed: vm2 was supposed to "scrub" exceptions before sending them into user code.

References & Further Reading

- vm2 Official Security Advisory
- NVD Entry for CVE-2023-29199
- vm2 Release v3.9.16 (Patch)

If you want more info, those links will have everything you need.

How Was It Fixed?

The bug was patched in version 3.9.16. The developers fixed the sanitizer so all exceptions are always handled—no more leaks, no more unsanitized host errors, no more sandbox escapes.

How Do I Fix My Project?

It's easy: Update to vm2 version 3.9.16 or later.

npm install vm2@latest

After you update, double-check your code to avoid any possible surprises.

Bottom Line

CVE-2023-29199 was a real wakeup call: Sandboxing isn’t perfect, especially when it comes to fast-moving technologies like Node.js. If you use vm2, patch now—and be cautious about trusting _any_ sandbox or plugin environment. Security is a moving target, but quick updates and solid monitoring go a long way!

Timeline

Published on: 04/14/2023 19:15:00 UTC
Last modified on: 04/25/2023 15:14:00 UTC