How to run untrusted code serverside?

All libraries I’ve seen mentioned in such questions (vm2, jailed) are trying to isolate the node process itself. Those kind of “jails” are constantly broken and highly dependent on future upgrades to node‘s standard library to not expose another attack vector.

An alternative would be to use the V8::Isolate class directly. It is meant to isolate JavaScript in Google Chrome & node, so you can expect it to be fully maintained, and more secure than you, I or a single library maintainer would ever be able to do.
This class is only able to run “pure” JavaScript. It has the full ECMAScript implementation, but no browser API or node API.
This is what is used by Cloudflare for their Worker product.

deno, the new language developed by node‘s creator, has an ambition of sandboxing by default using exactly the same thing and exposing parts of the standard library depending on the flags you enable.

In a node environment, you can use isolated-vm. It’s an amazing library that creates v8::Isolated subprocesses with the code you want to run in isolation.

It provides methods to pass values and functions to the isolate and back. This is not as trivial to use than most of the “jailing” libraries, but guarantees you an actual sandboxing of the JavaScript code.
As it’s “pure” JavaScript, the only escapes are the ones you provide under the form of injected functions.
Also, it gets automatically updated with each node version, as it uses node‘s own v8::Isolate.
One of the main pains is that if you want to inject libraries in your script, you will likely need to use a package bundler like webpack in order to bundle everything in a single script that can be used by the library.

I personally use it to run user-provided code in a crawler to extract information from a webpage using user provided code, and it works wonders.

Leave a Comment