Skip to content

Commit 925e3e6

Browse files
authored
Release 3.9.8 (#408)
Finalize release 3.9.8
1 parent 777ffb0 commit 925e3e6

File tree

11 files changed

+1155
-510
lines changed

11 files changed

+1155
-510
lines changed

.eslintrc.js

+18-18
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
module.exports = {
2-
env: {
3-
es6: true,
4-
node: true
5-
},
6-
extends: [
7-
'integromat'
8-
],
9-
parserOptions: {
10-
"ecmaVersion": 2017,
11-
"ecmaFeatures": {
12-
"globalReturn": true
13-
}
14-
},
15-
globals: {
16-
},
17-
rules: {
18-
}
19-
};
2+
env: {
3+
es6: true,
4+
node: true
5+
},
6+
extends: [
7+
'integromat'
8+
],
9+
parserOptions: {
10+
'ecmaVersion': 2017,
11+
'ecmaFeatures': {
12+
'globalReturn': true
13+
}
14+
},
15+
globals: {
16+
},
17+
rules: {
18+
}
19+
};

.github/workflows/node-test.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ jobs:
99
runs-on: ubuntu-latest
1010
strategy:
1111
matrix:
12-
node-version: [8, 10, 12, 14, 16]
12+
node-version: [8, 10, 12, 14, 16, 17]
1313
steps:
1414
- uses: actions/checkout@v2
1515
- name: Use Node.js ${{ matrix.node-version }}

CHANGELOG.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
v3.9.8 (TBD)
1+
v3.9.8 (2022-92-16)
22
-------------------
3-
[fix] Add function typecheck for arguments, caller, and callee property check (GeoffRen)
3+
[fix] Add function type check for arguments, caller, and callee property check (GeoffRen)
44
[fix] Fix find best extension handler
55

66
v3.9.7 (2022-02-10)
77
-------------------
88
[fix] Allow relative require from base script
9-
[fix] Fix issue with modules with exports clause in package json
9+
[fix] Fix issue with modules with exports clause in package JSON
1010
[fix] Added missing whitelist check before custom require
1111
[fix] Revert plain object toString behavior
1212
[fix] Root path check improved

index.d.ts

+12-8
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ import {EventEmitter} from 'events';
44
* Require options for a VM
55
*/
66
export interface VMRequire {
7-
/** Array of allowed builtin modules, accepts ["*"] for all (default: none) */
7+
/** Array of allowed built-in modules, accepts ["*"] for all. Using "*" increases the attack surface and potential
8+
* new modules allow to escape the sandbox. (default: none) */
89
builtin?: string[];
910
/*
1011
* `host` (default) to require modules in host and proxy them to sandbox. `sandbox` to load, compile and
11-
* require modules in sandbox. Builtin modules except `events` always required in host and proxied to sandbox
12+
* require modules in sandbox. Built-in modules except `events` always required in host and proxied to sandbox
1213
*/
1314
context?: "host" | "sandbox";
1415
/** `true`, an array of allowed external modules or an object with external options (default: `false`) */
@@ -17,7 +18,7 @@ export interface VMRequire {
1718
import?: string[];
1819
/** Restricted path(s) where local modules can be required (default: every path). */
1920
root?: string | string[];
20-
/** Collection of mock modules (both external or builtin). */
21+
/** Collection of mock modules (both external or built-in). */
2122
mock?: any;
2223
/* An additional lookup function in case a module wasn't found in one of the traditional node lookup paths. */
2324
resolve?: (moduleName: string, parentDirname: string) => string | undefined;
@@ -36,7 +37,7 @@ type CompilerFunction = (code: string, filename: string) => string;
3637
*/
3738
export interface VMOptions {
3839
/**
39-
* `javascript` (default) or `coffeescript` or custom compiler function (which receives the code, and it's filepath).
40+
* `javascript` (default) or `coffeescript` or custom compiler function (which receives the code, and it's file path).
4041
* The library expects you to have coffee-script pre-installed if the compiler is set to `coffeescript`.
4142
*/
4243
compiler?: "javascript" | "coffeescript" | CompilerFunction;
@@ -48,7 +49,7 @@ export interface VMOptions {
4849
*/
4950
timeout?: number;
5051
/**
51-
* If set to `false` any calls to eval or function constructors (`Function`, `GeneratorFunction`, etc) will throw an
52+
* If set to `false` any calls to eval or function constructors (`Function`, `GeneratorFunction`, etc.) will throw an
5253
* `EvalError` (default: `true`).
5354
*/
5455
eval?: boolean;
@@ -58,7 +59,7 @@ export interface VMOptions {
5859
wasm?: boolean;
5960
/**
6061
* If set to `true` any attempt to run code using async will throw a `VMError` (default: `false`).
61-
* @deprecated Use ``allowAsync` instead
62+
* @deprecated Use `allowAsync` instead.
6263
*/
6364
fixAsync?: boolean;
6465

@@ -76,7 +77,8 @@ export interface NodeVMOptions extends VMOptions {
7677
console?: "inherit" | "redirect" | "off";
7778
/** `true` or an object to enable `require` options (default: `false`). */
7879
require?: true | VMRequire;
79-
/** `true` to enable VMs nesting (default: `false`). */
80+
/** **WARNING**: This should be disabled. It allows to create a NodeVM form within the sandbox which could return any host module.
81+
* `true` to enable VMs nesting (default: `false`). */
8082
nesting?: boolean;
8183
/** `commonjs` (default) to wrap script into CommonJS wrapper, `none` to retrieve value returned by the script. */
8284
wrapper?: "commonjs" | "none";
@@ -119,6 +121,8 @@ export class VM {
119121
getGlobal(name: string): any;
120122
/** Freezes the object inside VM making it read-only. Not available for primitive values. */
121123
freeze(object: any, name?: string): any;
124+
/** Freezes the object inside VM making it read-only. Not available for primitive values. */
125+
readonly(object: any): any;
122126
/** Protects the object inside VM making impossible to set functions as it's properties. Not available for primitive values */
123127
protect(object: any, name?: string): any;
124128
}
@@ -135,7 +139,7 @@ export class NodeVM extends EventEmitter implements VM {
135139
/**
136140
* Create NodeVM and run code inside it.
137141
*
138-
* @param {string} script Javascript code.
142+
* @param {string} script JavaScript code.
139143
* @param {string} [filename] File name (used in stack traces only).
140144
* @param {Object} [options] VM options.
141145
*/

lib/nodevm.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,8 @@ class NodeVM extends VM {
262262
const {
263263
Module,
264264
jsonParse,
265-
createRequireForModule
265+
createRequireForModule,
266+
requireImpl
266267
} = closure(HOST, {
267268
__proto__: null,
268269
argv,
@@ -278,11 +279,12 @@ class NodeVM extends VM {
278279
_Module: {__proto__: null, value: Module},
279280
_jsonParse: {__proto__: null, value: jsonParse},
280281
_createRequireForModule: {__proto__: null, value: createRequireForModule},
282+
_requireImpl: {__proto__: null, value: requireImpl},
281283
_cacheRequireModule: {__proto__: null, value: null, writable: true}
282284
});
283285

284286

285-
resolver.init(this, ()=>true);
287+
resolver.init(this);
286288

287289
// prepare global sandbox
288290
if (sandbox) {
@@ -331,10 +333,12 @@ class NodeVM extends VM {
331333
const path = this._resolver.pathResolve('.');
332334
let mod = this._cacheRequireModule;
333335
if (!mod || mod.path !== path) {
334-
mod = new (this._Module)(this._resolver.pathConcat(path, '/vm.js'), path);
336+
const filename = this._resolver.pathConcat(path, '/vm.js');
337+
mod = new (this._Module)(filename, path);
338+
this._resolver.registerModule(mod, filename, path, null, false);
335339
this._cacheRequireModule = mod;
336340
}
337-
return mod.require(module);
341+
return this._requireImpl(mod, module, true);
338342
}
339343

340344
/**

lib/setup-node-sandbox.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -459,5 +459,6 @@ return {
459459
__proto__: null,
460460
Module,
461461
jsonParse: JSON.parse,
462-
createRequireForModule
462+
createRequireForModule,
463+
requireImpl
463464
};

lib/transformer.js

+19-11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11

22
const {parse: acornParse} = require('acorn');
33
const {full: acornWalkFull} = require('acorn-walk');
4+
const {compileFunction} = require('vm');
45

56
const INTERNAL_STATE_NAME = 'VM2_INTERNAL_STATE_DO_NOT_USE_OR_PROGRAM_WILL_FAIL';
67

@@ -26,21 +27,28 @@ function transformer(args, body, isAsync, isGenerator) {
2627
code += '\n})';
2728
}
2829

29-
const ast = acornParse(code, {
30-
__proto__: null,
31-
ecmaVersion: 2020,
32-
allowAwaitOutsideFunction: args === null && isAsync,
33-
allowReturnOutsideFunction: args === null
34-
});
30+
let ast;
31+
try {
32+
ast = acornParse(code, {
33+
__proto__: null,
34+
ecmaVersion: 2020,
35+
allowAwaitOutsideFunction: args === null && isAsync,
36+
allowReturnOutsideFunction: args === null
37+
});
38+
} catch (e) {
39+
// Try to generate a nicer error message.
40+
compileFunction(code);
41+
throw e;
42+
}
3543

3644
if (args !== null) {
3745
const pBody = assertType(ast, 'Program').body;
38-
if (pBody.length !== 1) throw new Error('Invalid arguments');
46+
if (pBody.length !== 1) throw new SyntaxError('Single function literal required');
3947
const expr = pBody[0];
40-
if (expr.type !== 'ExpressionStatement') throw new Error('Invalid arguments');
48+
if (expr.type !== 'ExpressionStatement') throw new SyntaxError('Single function literal required');
4149
const func = expr.expression;
42-
if (func.type !== 'FunctionExpression') throw new Error('Invalid arguments');
43-
if (func.body.start !== argsOffset + 3) throw new Error('Invalid arguments');
50+
if (func.type !== 'FunctionExpression') throw new SyntaxError('Single function literal required');
51+
if (func.body.start !== argsOffset + 3) throw new SyntaxError('Unexpected end of arg string');
4452
}
4553

4654
const insertions = [];
@@ -79,7 +87,7 @@ function transformer(args, body, isAsync, isGenerator) {
7987
});
8088
} else if (type === 'Identifier') {
8189
if (node.name === INTERNAL_STATE_NAME) {
82-
throw new Error('Use of internal vm2 state variable');
90+
throw new SyntaxError('Use of internal vm2 state variable');
8391
}
8492
} else if (type === 'ImportExpression') {
8593
insertions.push({

0 commit comments

Comments
 (0)