isolated-vm
isolated-vm copied to clipboard
How to prevent the main thread from getting blocked?
Hey there,
So i made this script to show off the problem:
const ivm = require("isolated-vm");
const isolate = new ivm.Isolate({ memoryLimit: 128 });
const context = isolate.createContextSync();
const jail = context.global;
jail.setSync("global", jail.derefInto());
context.evalClosureSync(
`
globalThis.log = (...args) => {
return $0.apply(undefined, args, { arguments: { copy: true }, result: { promise:true, copy: true } });
};
`,
[
(...a) => {
console.log(a);
while (true) {}
},
],
{
arguments: { reference: true },
}
);
setInterval(() => {
console.log(isolate.cpuTime + "");
}, 250);
context.eval('log("hello world")');
The function basicly runs in the main thread so it is blocking the main thread and the CPU time is not showing. How can i make it so the main thread is not blocking? I expect the CPU time to be logged every 250 ms.
@BartTactick Were you able to find a solution?
@traviscooper No solution yet, seems like the code in functions like this are ran in the main thread therefore not counting the CPU time.
I don't think args are provided by the untrusted code, so it makes sense why that function can run outside of the sandbox (if it didn't I guess the console.log
would also not work since it would log in the child process). The solution would be not pass random and untrusted arguments (why do that?).
But if you still want your argument to be blocking and not block the main thread, you can always run ivm
in separate Node process using child_process
. With the IPC however you won't be likely to watch for the CPU time from isolate
class in child process as the limitation due to the serialization – at best, you might be able to observe the details about the entire child process using their PID.
I don't think args are provided by the untrusted code, so it makes sense why that function can run outside of the sandbox (if it didn't I guess the
console.log
would also not work since it would log in the child process). The solution would be not pass random and untrusted arguments (why do that?).But if you still want your argument to be blocking and not block the main thread, you can always run
ivm
in separate Node process usingchild_process
. With the IPC however you won't be likely to watch for the CPU time fromisolate
class in child process as the limitation due to the serialization – at best, you might be able to observe the details about the entire child process using their PID.
Thats true, however i dont feel like child_process is a good solution since the CPU time doenst increase either. Do you know a good solution? (for example if i loop 1000 times in an attached function, it wont increase the cpu time of the isolate)
evalClosureSync
All the *Sync
method runs in the main thread. While your callback is also defined in the main isolate/thread, it will be run in the main isolate/thread as well.
Only if you run the async
version of the evals, as well as the while (true)
loop, is defined and run in the other isolate, it will not block the main thread.