isolated-vm: running untrusted JavaScript in separate V8 isolates on Node.js
Secure & isolated JS environments for nodejs
At a glance
- What is it?
- isolated-vm exposes V8's Isolate interface to Node.js so you can run code in a fresh JavaScript environment with no Node.js capabilities. It is a native addon in maintenance mode, which shapes both who should use it and how much work adoption costs.
- Who is it for?
- Adopt isolated-vm when you need to execute third-party or user-supplied JavaScript inside a Node.js process and you can accept a native addon, a compiler on every build machine, and version pinning to the Node.js release line. Do not adopt it if you want a pure JavaScript sandbox, if you are on an odd-numbered Node.js release, or if you expect the experimental branch to be production ready.
- Can I use it commercially?
- Yes. ISC is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 25, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem isolated-vm solves for Node.js
Node's built-in vm module runs code in the same V8 isolate as your application. The README's own framing of isolated-vm is that it gives you access to v8's Isolate interface, which lets you create JavaScript environments completely isolated from each other. That distinction is the whole product. Inside an isolate created by this library, the code has a fresh JavaScript environment free of the extra capabilities the Node.js runtime normally provides, so there is no require, no process, no fs, and no shared heap with your host code.
The audience follows from that. The README lists Screeps running player-supplied code that persists for days, Fly running globally distributed applications, Algolia executing user-provided code for content extraction in its Custom Crawler, and Tripadvisor server-side rendering thousands of React pages per second. These are all cases where code you did not write has to execute inside a process you control. If your code is your own and trusted, you do not need this library at all.
How an isolate, a context and a reference fit together
The API is built around marshalling data between isolates, because isolates share no resources with each other. The README states this directly: since isolates share no resources, most of the API exists to provide primitives that make moving data between many isolates quick and easy. The classes named in the table of contents are Isolate, Context, Script, Module, Callback, Reference and ExternalCopy, and several of them are marked transferable.
A Reference is the mechanism for reaching from one isolate into another. It is also the main hazard. The security section warns that you should not leak any instance of an isolated-vm object, naming Reference and ExternalCopy, into untrusted code, because an attacker can use such an instance as a springboard back into the Node.js isolate and from there take complete control of the process. Read that as an architectural constraint rather than a footnote: the boundary you are defending is the set of objects you hand across, not the JavaScript syntax you allow.
The README also recommends keeping instances of isolated-vm in a different Node.js process from other critical infrastructure, and says that if advanced persistent threats are in your threat model you should architect along the lines of Chromium's site isolation and keep the kernel patched against local privilege escalation. Container escape attacks are called out as something to research if you run in Docker. None of that is optional hardening; it is the threat model the author states.
Installing isolated-vm and running a first script
Installation compiles a native addon. The package.json install script runs node-gyp-build with a node-gyp rebuild fallback, and the README says that to install the module you need a compiler, with per-distribution package lists for Ubuntu, Alpine, Amazon Linux AMI, Arch and Red Hat. The published compatibility table maps Node.js 22.x to isolated-vm 5.x or 4.x, Node.js 24.x to 6.x or 5.x, and Node.js 26.x to 7.x. The package.json in the repository declares engines node >=24.0.0 for version 7.0.1, so the version you install and the Node.js you run are coupled.
The README instructs you to install the module with npm, and warns that if you run into errors while running that install it is likely you do not have a compiler set up, or your compiler is too old.
npm install isolated-vmThe README states a requirement that is easy to miss: if you are using a version of nodejs 20.x or later, you must pass --no-node-snapshot to node. The README does not spell out what breaks without it, only that the flag is required.
node --no-node-snapshotA first use creates an isolate, creates a context inside it, compiles a script, and then reads a value back out. The README documents Isolate, Context and Script as transferable classes, and the examples section of the README is where the working code lives. The repository also ships isolated-vm.d.ts for TypeScript users, which is the file to read for exact method signatures before you write the first script. What you should see, once a script runs in a context, is a value returned from an environment that has no access to your application's globals. From there the real work is deciding what crosses the boundary: ExternalCopy for values you want to move, and Reference for functions you deliberately expose. The README's API documentation is the place to check each of those before you expose anything.
Maintenance mode and the Node.js version treadmill
The README states plainly that isolated-vm is currently in maintenance mode and will be supported for as long as is technically feasible. A separate experimental branch holds a new version the author has been working on for some time, described as worth looking at but certainly not ready for serious applications. Treat the experimental branch as a research artifact, not a migration target.
The upgrade cost is the compatibility table. Because the library binds to V8 through native code, each supported Node.js major has a matching isolated-vm range, and the README says odd-numbered Node.js releases cannot be supported at this time, in part because they frequently break ABI and API compatibility. The security section adds that keeping Node.js current matters because point releases ship V8 updates, and it notes there have usually been three to five such updates within a single LTS cycle. In practice this means your Node.js upgrade and your isolated-vm upgrade are one decision, not two, and your CI image needs a compiler or a prebuilt binary for the exact platform and runtime you target.
Where isolated-vm is the wrong tool
The README is unusually direct that this library does not make your application safe by itself. Running untrusted code is described as an extraordinarily difficult problem, and misuse or carelessness can leak sensitive data or grant undesired privileges to an isolate. If your plan is to install a package and consider the sandbox solved, this is not that package.
The second limitation is resilience. The README notes that plain JavaScript can still crash, hang, or disrupt a process, and that your application must be resilient to those attacks. An isolate gives you memory separation and a clean global environment; it does not give you a wall-clock timeout policy, a supervisor, or a restart strategy. The README's suggestion to keep isolated-vm instances in a separate Node.js process is the practical answer, and it means you are building process management on top of the library.
Third, if you need a pure JavaScript sandbox with no native build step, this is the wrong category of tool. The compiler requirement on every install and the engines constraint in package.json are not incidental; they are the cost of the isolation model.
isolated-vm versus vm2 and the built-in vm module
The README has an alternatives section, and the search questions people ask are about isolated-vm versus vm2 and isolated-vm versus vm. The difference in approach is where the boundary sits. Node's vm module runs code in the same isolate, so a sandbox escape is a step within one process's JavaScript environment. vm2 was a widely used pure JavaScript sandbox built on top of that same runtime model. isolated-vm instead asks V8 for a separate Isolate, so the untrusted code does not share a heap or a set of globals with your application in the first place.
That approach buys a stronger boundary and costs a native addon. You need a compiler, you need the Node.js version to match the compatibility table, and you need --no-node-snapshot on modern Node.js. The README's security guidance is also more demanding than a pure JavaScript sandbox's, because the objects you pass across the boundary are the attack surface. Choose isolated-vm when the isolation boundary is the point. Choose a same-isolate approach when you want no build step and the code you run is only lightly untrusted.
Licence and the cost of staying on a supported combination
isolated-vm is licensed under ISC, which the package.json and the repository LICENSE file both state, and the README badge links to that file. ISC is a permissive licence, so the practical implication for most teams is attribution rather than copyleft obligations. This is a statement about what the repository declares, not legal advice; if your organisation has a licence review process, the file to hand it is LICENSE at the repository root.
The recurring cost is the version matrix. A supported combination is a Node.js major, an isolated-vm range, and a build toolchain that can compile the addon, plus the --no-node-snapshot flag where the README requires it. The Dockerfile.alpine and Dockerfile.debian entries at the repository root are the reference for what a working build environment looks like, and the scripts directory holds the prebuild tooling. If your deployment cannot run a compiler and cannot use a prebuilt binary for your target, this library will not install, and no amount of configuration will change that.
Editorial conclusion
Adopt isolated-vm when you need to execute third-party or user-supplied JavaScript inside a Node.js process and you can accept a native addon, a compiler on every build machine, and version pinning to the Node.js release line. Do not adopt it if you want a pure JavaScript sandbox, if you are on an odd-numbered Node.js release, or if you expect the experimental branch to be production ready. Verify three things before committing: that your Node.js version matches the compatibility table, that you pass --no-node-snapshot on Node.js 20 or later, and that no Reference or ExternalCopy instance can reach untrusted code in your design.
Frequently asked questions
How do I install isolated-vm?
Install it with npm, but make sure a compiler is available first, since the package builds a native addon. The README lists the packages to install on Ubuntu, Alpine, Amazon Linux AMI, Arch and Red Hat, and points Windows and macOS users at the node-gyp instructions.
What is the isolated-vm module?
It is a Node.js library that gives you access to V8's Isolate interface, so you can create JavaScript environments that are completely isolated from each other and free of the extra capabilities the Node.js runtime provides. Its API is mostly primitives for marshalling data between isolates, since isolates share no resources.
How does isolated-vm differ from vm2?
isolated-vm creates a separate V8 Isolate, so the untrusted code does not share a heap or globals with your application, whereas a sandbox built on Node's vm module runs inside the same isolate. The trade-off is that isolated-vm is a native addon that needs a compiler and a matching Node.js version.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/laverdet-isolated-vm)
Community notes