Javascript Sandbox for your Node Project

Utkarsh Mehta
Aug 7, 2020 · 3 min read
Image for post
Image for post

I recently encountered a situation in the client project, where I was expected to run custom user-provided code, inside my Node environment to transform data. We all know the security implication of opening up our server runtime to external code and if not done correctly, the results are deadly ranging from losing our user’s data to raising our cloud servers bills because of mining injections.

Fortunately, there is a package called vm2 which provides a sandbox for such situations so that we can provide the flexibility for our users and also keep our servers safe. Let us see how it can be configured and used.

Some pointers for the sandbox:

  1. Uses console output of Node process
  2. Can require external & builtin modules
  3. Has the ability to setup customized access to builtin modules
  4. Uses secure context for execution using VM module
  5. Uses proxies to keep the sandbox code isolated

Let’s get into the implementation,

Here we are using the NodeVM module from vm2 to run the code & we have declared UtilFunctions. If you want to provide a facility to call an API, query database, etc safely, you can just declare functions and make them available to the sandbox. In this way, you won’t have to be worried about providing access to libraries to the sandbox and malicious users exploiting it.

As the functionality is abstracted from the sandbox, all users can do is to call the functions and use the return value if any.

Here we are configuring the NodeVM to get the sandbox. We are disabling eval, wasm, external modules, setTimeout & setInterval. Also, we are not allowing any builtin modules to be used in the code. We are making the sandbox secure and execution swift with this config. Also, we are injecting the UtilFunction into the sandbox.

Here we have declared function _uncaughtException to handle uncaughtExceptions thrown by VM. Function registerListeners will add the listener to VM and function cleanup will remove the listener from VM. This part is just to make sure the Node process won’t exit due to the user entered code.
Moving on to executeJS function where all the magic happens, NodeVM uses callbacks in the sandbox i.e. (after the execution of code a callback will be called by sandbox to convey the result of execution) but usually, we prefer async/await for such functionality as some code will be waiting for the result of user JS execution.

Image for post
Image for post

So using promises we made this function async. Now executeJS take 2 arguments code & context. Context is a JSON object which is made available to the user entered JS code, code can make changes to context and after execution, context can be used further. In this way, we make sure that the JS execution sandbox is working as a transformer. Which at the core just modifies the context. But due to this structure for the Node process, the executeJS function is a BlackBox transformer making it better streamlined with your existing system.
Next, we declare func, which is nothing but the user entered code enclosed in a function that is exported. Now we have taken care of exception handling with the exported function itself. As we discussed that VM uses callbacks so we are passing context in the first argument and 2 callbacks to handle success(resolve) & failure(reject) cases. Then we will register listeners to VM. vm.run will return the exported function we formulated in func.
The final step is to call the exported function and passing context & callbacks. In the callbacks, we are calling cleanup to remove listeners from VM and resolving or rejecting the promise accordingly.
Let’s test this,

So, in our test, the code has the user entered code, which

  1. Checks the context for date and day
  2. Uses isHoliday UtilFunction to check if its holiday
  3. Checks for weekend
  4. Sets plan on the context accordingly or throw an exception

The executeJS function will return modified ctx or throw exception according to data.

Thanks for reading… keep hacking…

Tarka Labs Blog

Tarka Labs is a team of passionate hackers, designers and…

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store