diff --git a/lib/fixasync.js b/lib/fixasync.js new file mode 100644 index 0000000..5d9b091 --- /dev/null +++ b/lib/fixasync.js @@ -0,0 +1,110 @@ +'use strict'; + +// eslint-disable-next-line no-invalid-this, no-shadow +const {GeneratorFunction, AsyncFunction, AsyncGeneratorFunction, global, Contextify, host} = this; +// eslint-disable-next-line no-shadow +const {Function, eval: eval_, Promise, Object, Reflect, RegExp, VMError} = global; +const {setPrototypeOf, getOwnPropertyDescriptor, defineProperty} = Object; +const {apply: rApply, construct: rConstruct} = Reflect; +const {test} = RegExp.prototype; + +function rejectAsync() { + throw new VMError('Async not available'); +} + +const testAsync = setPrototypeOf(/\basync\b/, null); + +function checkAsync(source) { + // Filter async functions, await can only be in them. + if (rApply(test, testAsync, [source])) { + throw rejectAsync(); + } + return source; +} + +const AsyncCheckHandler = { + __proto__: null, + apply(target, thiz, args) { + let i; + for (i=0; i { }); } + it('async', () => { + const vm2 = new VM({fixAsync: true}); + assert.throws(() => vm2.run('(async function(){})'), /Async not available/, '#1'); + assert.throws(() => vm2.run('new Function("as"+"ync function(){}")'), /Async not available/, '#2'); + assert.throws(() => vm2.run('new (function*(){}).constructor("as"+"ync function(){}")'), /Async not available/, '#3'); + assert.throws(() => vm2.run('Promise.resolve().then(function(){})'), /Async not available/, '#4'); + if (Promise.prototype.finally) assert.throws(() => vm2.run('Promise.resolve().finally(function(){})'), /Async not available/, '#5'); + if (Promise.prototype.catch) assert.throws(() => vm2.run('Promise.resolve().catch(function(){})'), /Async not available/, '#6'); + assert.throws(() => vm2.run('eval("as"+"ync function(){}")'), /Async not available/, '#7'); + assert.strictEqual(vm2.run('Object.getPrototypeOf((function*(){}).constructor)'), vm2.run('Function'), '#8'); + assert.throws(() => vm2.run('Function')('async function(){}'), /Async not available/, '#9'); + }); + it('various attacks #1', () => { const vm2 = new VM({sandbox: {log: console.log, boom: () => { throw new Error();