Comments (5)
The timeout only applies to the initial synchronous execution. In this case your anonymous function is invoked, it invokes externalFunction
which immediately returns a promise. Then myfunc()
returns a promise and evaluation has finished.
The promise-related convenience utilities present a challenge when invoked against untrusted code which needs to timeout.
from isolated-vm.
This makes so much sense, can't believe I didn't notice that...
Also makes me realize that my workaround doesn't really work :
import ivm from 'isolated-vm';
const isolate = new ivm.Isolate();
const context = await isolate.createContext();
// Set a reference to a function outside of the isolate
context.global.set(
'externalFunctionRef',
new ivm.Reference(async (params) => {
// Asynchronous code here (database query, http request, etc...)
})
);
// Make a function in the isolate to abstract the call to the external function
context.evalIgnored(`
let started;
const externalFunction = async (params) => {
if(Date.now() > started + 5000) throw "Timeout reject the promise";
return await externalFunctionRef.apply(null, [params], {
arguments: { copy: true },
result: { copy: true, promise: true },
});
};`);
// Later on...
// Run the actual code inside the isolate
const code = `started = Date.now(); // I inject this before the "untrusted code" (in my actual use case, the code is transpiled so I have control on the variable names used in the user code, they wouldn't be able to alter this value)
const myfunc = async ()=>{
let firstTime = true;
while(true){
if(firstTime) await externalFunction(); // myfunc will return a promise here
firstTime = false; // The promise never resolves and can't be rejected by externalFunction because externalFunction doesn't get called anymore...
}}; myfunc();`;
try {
console.log(
'RESULT: ' +
(await context.eval(code, {
timeout: 5000,
promise: true,
copy: true,
}))
);
} catch (e) {
console.error(e);
}
I guess I could add the same timeout check that I do in externalFunction at the beginning of while and for loops during transpilation.
Would that cover everything to prevent infinite code execution ?
They could still write recursive code but they'll hit the max call stack size and stop eventually.
from isolated-vm.
Would calling isolate.dispose() force the pending promise to reject ?
from isolated-vm.
If you want to have a timeout which is cumulative between multiple entrances of the isolate, and also includes asynchronous wall time, then you'll need to handle that bookkeeping outside of isolated-vm.
The problem is not simple. For example you need to make sure that await Promise.all([ externalFunction(), externalFunction() ])
doesn't "charge" the user for 2x wall time.
My advice here is to pretend that { promise: true }
does not exist and instead pass around your own resolver functions.
from isolated-vm.
Thanks for the help.
I think for my use case I'll go with this for now:
import ivm from 'isolated-vm';
const isolate = new ivm.Isolate();
const context = await isolate.createContext();
// Set a reference to a function outside of the isolate
context.global.set(
'externalFunctionRef',
new ivm.Reference(async (params) => {
// Asynchronous code here (database query, http request, etc...)
})
);
// Make a function in the isolate to abstract the call to the external function
context.evalIgnored(`
let started;
const externalFunction = async (params) => {
if(Date.now() > started + 5000) throw "Timeout reject the promise";
return await externalFunctionRef.apply(null, [params], {
arguments: { copy: true },
result: { copy: true, promise: true },
});
};`);
// Later on...
// Run the actual code inside the isolate
const code = `started = Date.now(); // I inject this before the "untrusted code" (in my actual use case, the code is transpiled so I have control on the variable names used in the user code, they wouldn't be able to alter this value)
const myfunc = async ()=>{
let firstTime = true;
while(true){
if(firstTime) await externalFunction(); // myfunc will return a promise here
firstTime = false; // The promise never resolves and can't be rejected by externalFunction because externalFunction doesn't get called anymore...
}}; myfunc();`;
let promiseRef;
try {
promiseRef = context.eval(code, {
timeout: 5000,
promise: true,
copy: true,
});
console.log(
'RESULT: ' +
(await Promise.race([
promiseRef,
new Promise((resolve, reject) => {
setTimeout(() => reject('TIMED OUT'), 5000);
}),
]))
);
} catch (e) {
console.error(e);
} finally {
if (!isolate.isDisposed) isolate.dispose();
setTimeout(() => console.log(promiseRef), 1000);
}
I don't mind the infinite loop running for a little while longer in the isolate as long as it doesn't stop my main process awaiting it and the Promise gets rejected when the isolate is disposed of.
from isolated-vm.
Related Issues (20)
- Compile errors with node 22 on archlinux HOT 2
- unable to modify built-in object prototypes HOT 3
- Next.js: `new ivm.Isolate()` aborts the whole application without errors HOT 3
- Error: Cannot find module './out/isolated_vm' HOT 3
- how can i set js breakpoint on first line, Implement the stopOnEntry HOT 2
- How to access proto methods of the returned reference? HOT 3
- `ModuleNotFoundError: No module named 'distutils'` on Vercel starting from version `4.8.0` HOT 3
- Is there any way to request garbage collector inside an isolate? HOT 5
- npm init directus-project . throwing error
- Passing Object as a reference to the isolated VM and expecting the properties of the original object should also be modified. HOT 1
- vitest and isolted-vm incompatible? HOT 1
- TypeError: function XXX could not be cloned. HOT 1
- Cannot create sandbox like previous vm library HOT 1
- Error: /lowcode/node_modules/isolated-vm/out/isolated_vm.node: invalid ELF header HOT 2
- Asynclocalstorage context is undefined when its been called second time HOT 2
- can not build universal macos application package with it HOT 1
- Web APIs not available in isolated-vm? HOT 1
- Cannot access to reference within another reference HOT 1
- Add node-gyp as peer dependency HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from isolated-vm.