How to use node modules inside VM2 sandbox

2k views Asked by At

I'm trying to run a user-submitted script in a sandbox to process some data, before sending the output to a specified end point through a http request via node-fetch. However, I'm not sure if I am even doing it correctly, even after reading the documentation for VM2, I'm not completely certain of what options I need to configure.

Here is an example, where I call process(); inputData is { a: 123 }, and userScript will be the sampleScript.js shown below.

process(inputData, userScript) {
  const { NodeVM } = require('vm2');
  const vm = new NodeVM({
        console: 'inherit',
        sandbox: { content: inputData },
        require: { external: true },
        wrapper: 'none',
      });
  console.log(vm.run(userScript, 'node_modules'));
}

sampleScript.js

input = content;

function execute(data) {
  data['a'] *= 100;
  const fetch = require('node-fetch');
  await fetch(`webhook.site-endpoint`, {
      method: 'POST',
      body: JSON.stringify(data),
    });
}
execute(input);

I should be expecting a message '12300' on the specified endpoint. However, seems like there is something wrong with the await fetch method call, as I am getting this error on my console:

(node:36376) UnhandledPromiseRejectionWarning: Error: connect ECONNREFUSED 127.0.0.1:80 at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1141:16) (node:36376) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode).

It might just be the way I configured the options of the sandbox, as I am not sure if I have successfully imported the node-fetch library in the first place. Any advice would be appreciated!

1

There are 1 answers

0
Rajkumar Gaur On

You successfully imported the module by passing the node_modules as the second argument, given that there is node-fetch in your node_modules.

The error, on the other hand, is saying that there was an error while processing a promise but it was unhandled (await was incorrectly used).

The error is also saying about Connection refused, which means node-fetch tried to connect, so node-fetch is working fine. The problem maybe with the URL.

The problem is with the code, I can see that a few things are wrong.

  1. You are using await inside a function that is not async. Use async function execute(data){} instead
  2. There might probably be an error in the fetch command, you should catch it by wrapping it in a try-catch block

The updated code should look like this

input = content;

async function execute(data) {
  try {
    data['a'] *= 100;
    const fetch = require('node-fetch');
    await fetch(`webhook.site-endpoint`, {
      method: 'POST',
      body: JSON.stringify(data),
    });
  }
  catch(err) {
    console.error(err)
  }
}
execute(input);