0

Lately am building an API with Node.js that receives untrusted code to run it using vm2. The issue is I want to run async functions, so I need to use NodeVM which does not support timeout for infinite loop, the solutions that I found all about using child process then kill it if it's not working.

But I am receiving the code as a string and I want to prevent having an infinite loop in it, so I thought of using regex to inject the while/for loop with a timeout condition or something so throw an exception whenever infinite loop happened.

Is that possible?

VLAZ
  • 26,331
  • 9
  • 49
  • 67
DanTe
  • 115
  • 6
  • no matter how awesome your regex is, there will always be a way for your users to provide their code in a way you didn't think of while writing your regex, crashing their code for no reason. I'm not familiar with vm2, but isn't the whole idea to run it in a separate process? Otherwise the executed code will always have access to global variables (that includes environment variables that you don't necessarily want to expose) – Kamil Janowski Jun 28 '20 at 08:05
  • @KamilJanowski you are right, the purpose of vm2 is to run the code separately, the issue is node.js is single-threaded so having an open loop will make the server stuck in an infinite loop. – DanTe Jun 28 '20 at 09:00

2 Answers2

0

The perfect solution that worked for me is to use AST. so I learned more about it so I can inject the string with anything anywhere I want.

Then I followed these steps:

1- convert string code to AST using Esprima parser.

2- Inject the Infinite loop code protection, which is:

// Before any loop
let myvar = Date.now();
// Inside the loop
if (Date.now() - myvar > 1000) { break;}

use break or throw an error, notice that you need a unique variable name generator every time you catch a loop.

3- Convert it back to a string using escodegen.

DanTe
  • 115
  • 6
0

You can never be sure that user-supplied code executes in a good manner without blocking your node process. For example, CPU intensive calculations will block the main node process. The best solution is to execute such code in its own process and stop that process if it doesn't finish in time.

worker-farm is a package that has a simple API to start worker processes with a configurable timeout. Execute the user-provided code in such a worker instead of your main node process.

If you want to restrict the user code from using certain libraries, you can use VM2 to achieve that.

Jaroslav K
  • 327
  • 1
  • 13