diff --git a/src/trusted/impl/bare/bareSandbox.ts b/src/trusted/impl/bare/bareSandbox.ts index dc7fd64..6744890 100644 --- a/src/trusted/impl/bare/bareSandbox.ts +++ b/src/trusted/impl/bare/bareSandbox.ts @@ -21,9 +21,11 @@ import setupSandboxListeners from '~trusted/lib/setupSandboxListeners.js'; import createErrorEventListenerFactory from '~untrusted/lib/createErrorEventEventListenerFactory.js'; import createMessageEventListenerFactory from '~untrusted/lib/createMessageEventListenerFactory.js'; +/* +TODO: These should be exported or called upon creating bareSandbox. +TODO: Fix issues with Node.js and freezePrototypes */ hardenGlobals(); freezePrototypes(); -// TODO: Freeze prototypes // TODO: wrap setTimeout and clearTimeout const bareSandbox: ISandbox = async ( diff --git a/src/untrusted/impl/nodejs/nodejsSandboxVm.inline.ts b/src/untrusted/impl/nodejs/nodejsSandboxVm.inline.ts index 04bb34a..0e7bbac 100644 --- a/src/untrusted/impl/nodejs/nodejsSandboxVm.inline.ts +++ b/src/untrusted/impl/nodejs/nodejsSandboxVm.inline.ts @@ -306,7 +306,7 @@ const nodejsSandbox = ( 'throw "Invalid call";' + // If source includes /*@lint@*/, the constructor is called just for // syntax validation - 'if(c(lio,src,"/*@lint@*/")!==-1)return;' + + 'if(c(lio,src,"/*@lint@*/")!==-1)return function(){};' + 'var tmp=ut;' + 'c=lio=ut=void 0;' + 'return tmp;' + diff --git a/src/untrusted/lib/singleUseFunctionConstructor.ts b/src/untrusted/lib/singleUseFunctionConstructor.ts index 6551192..5c6a82e 100644 --- a/src/untrusted/lib/singleUseFunctionConstructor.ts +++ b/src/untrusted/lib/singleUseFunctionConstructor.ts @@ -19,11 +19,11 @@ * * - If it is invoked as a function (e.g., `singleUseFunctionConstructor(...)`, * it behaves like the `Function` constructor, then immediately revokes itself - * after the function has been created. + * after the function has been called. * - If it is invoked using the `new` keyword (e.g., * `new singleUseFunctionConstructor(...)`, it behaves like the `Function` - * constructor, then immediately revokes itself after the function has been - * instantiated. + * constructor, then immediately revokes itself after function instantiated has + * been called. * * @returns {Function} A revocable version of the native `Function` constructor. * @@ -35,16 +35,40 @@ const singleUseFunctionConstructor = (() => { const FERAL_FUNCTION = Proxy.revocable(Function, {}); + const revocables: { (): void }[] = []; + + const p = (o: T) => + Proxy.revocable(o, { + ['apply'](target, thisArg, argArray) { + FERAL_FUNCTION.revoke(); + for (let i = 0; i < revocables.length; i++) { + revocables[i](); + } + revocables.length = 0; + const result = target.apply(thisArg, argArray); + return result; + }, + ['construct']() { + return undefined as unknown as object; + }, + ['getOwnPropertyDescriptor']() { + return undefined; + }, + ['getPrototypeOf']() { + return null; + }, + }); + return new Proxy(FERAL_FUNCTION.proxy, { ['apply'](target, thisArg, argArray) { - const result = target.apply(thisArg, argArray); - FERAL_FUNCTION.revoke(); - return result; + const r = p(target.apply(thisArg, argArray)); + revocables[revocables.length] = r.revoke; + return r.proxy; }, ['construct'](target, argArray) { - const result = new target(...argArray); - FERAL_FUNCTION.revoke(); - return result; + const r = p(new target(...argArray)); + revocables[revocables.length] = r.revoke; + return r.proxy; }, ['get']() { return undefined;