feat: vm2模块调整

This commit is contained in:
fofolee 2022-01-10 23:39:03 +08:00
parent 2b1f678bde
commit 72f098e104
19 changed files with 4309 additions and 39 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
.DS_Store
Thumbs.db
src/node_modules/

View File

@ -0,0 +1,9 @@
root = true
[*.js]
charset = utf-8
indent_style = tab
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

View File

@ -0,0 +1 @@
/test.js

View File

@ -0,0 +1,19 @@
module.exports = {
env: {
es6: true,
node: true
},
extends: [
'integromat'
],
parserOptions: {
"ecmaVersion": 2017,
"ecmaFeatures": {
"globalReturn": true
}
},
globals: {
},
rules: {
}
};

View File

@ -0,0 +1,164 @@
v3.9.5 (2021-10-17)
-------------------
[new] Editor config (aubelsb2)
[fix] Fix for Promise.then breaking
[fix] Fix for missing properties on CallSite
v3.9.4 (2021-10-12)
-------------------
[new] Added strict option
[fix] Security fixes (XmiliaH)
[fix] Fixed bound function causes TypeError (XmiliaH)
[fix] Allow extending of frozen objects
v3.9.3 (2020-04-07)
-------------------
[fix] Security fixes
[fix] Fixed problems when Promise object is deleted (XmiliaH)
[fix] Fixed oversight that write ability can change on non configurable properties (XmiliaH)
[fix] Support shebang as node does (XmiliaH)
[fix] Property typos (Shigma)
v3.9.2 (2020-04-29)
-------------------
[new] Added NodeVM options to pass argv & env to process object (XmiliaH)
[fix] Fixed breakouts in NodeVM (XmiliaH)
[fix] Made async check more robust (XmiliaH)
v3.9.1 (2020-03-29)
-------------------
[fix] Require helpers statically in main (XmiliaH)
[fix] Fix for non-configurable property access (XmiliaH)
v3.9.0 (2020-03-21)
-------------------
[new] Added vm.Script `lineOffset` and `columnOffset` options (azu)
[new] Allow to specify a compiler per VMScript (XmiliaH)
[new] Add option to disable async (XmiliaH)
[new] Added allot of jsdoc (XmiliaH)
[fix] Fix access to frozen or unconfigurable properties (XmiliaH)
[fix] Double wrap Objects to prevent breakout via inspect (XmiliaH)
[fix] Compile now compiles VM code (XmiliaH)
v3.8.4 (2019-09-13)
-------------------
[fix] Do not allow precompiling VMScript (XmiliaH)
[fix] Security fixes (XmiliaH)
v3.8.3 (2019-07-31)
-------------------
[fix] Security fixes
v3.8.2 (2019-06-13)
-------------------
[fix] toString() on builtin objects
v3.8.1 (2019-05-02)
-------------------
[fix] Module resolver fixes
[fix] require('events') works correctly in Node 12
[fix] SyntaxError not being instanceOf Error
v3.8.0 (2019-04-21)
-------------------
[new] Allow prohibiting access to eval/wasm in sandbox context
[new] Allow transitive external dependencies in sandbox context (Idan Attias)
[new] Allow using wildcards in module-names passed using the external attribute (Harel Moshe)
[fix] Default to index.js when specified "main" does not exist (Harel Moshe)
[fix] Security fixes
v3.7.0 (2019-04-15)
-------------------
[new] Add require.resolve (Idan Attias)
[new] Support multiple root paths (Idan Attias)
v3.6.11 (2019-04-08)
-------------------
[fix] Contextification of EvalError and URIError
[fix] Security fixes
v3.6.10 (2019-01-28)
-------------------
[fix] Add missing console.debug function in NodeVM
[fix] Security fixes
v3.6.9 (2019-01-26)
-------------------
[fix] Security fixes
v3.6.8 (2019-01-26)
-------------------
[fix] Security fixes
v3.6.7 (2019-01-26)
-------------------
[fix] Security fixes
v3.6.6 (2019-01-01)
-------------------
[fix] Security fixes
v3.6.5 (2018-12-31)
-------------------
[fix] Security fixes
v3.6.4 (2018-10-17)
-------------------
[fix] Added new to vmwerror when trying to load coffeescipt but can't (dotconnor)
[fix] Add arguments to process.nextTick proxy (Patrick Engström)
v3.6.3 (2018-08-06)
-------------------
[fix] Security fixes
v3.6.2 (2018-07-05)
-------------------
[fix] Security fixes
v3.6.1 (2018-06-27)
-------------------
[fix] Security fixes
v3.6.0 (2018-05-11)
-------------------
[new] Support for custom source extensions
[new] WIP support for disallowing Promise
[fix] Prevent slow unsafe alloc for Buffers
[fix] Refactors around defaults
[fix] Types definition update
v3.5.2 (2017-10-04)
-------------------
[fix] Prevent slow unsafe alloc for Buffers
v3.5.1 (2017-10-04)
-------------------
[fix] Prevent unsafe alloc for Buffers
v3.5.0 (2017-08-31)
-------------------
[new] Allow a custom compiler to recieve the filetype (Orta Therox)
[new] Allow in-sandbox requires to also get called through the compiler (Orta Therox)
[new] Support whitelisting modules inside a VM (Orta Therox)
[new] Add TypeScript definition (Orta Therox)
v3.4.0 (2017-03-28)
-------------------
[new] Added experimental VM.protect method
v3.3.1 (2017-03-27)
-------------------
[new] Added VM.freeze method
v3.2.0 (2017-02-10)
-------------------
[new] Added support for pre-compiled scripts via VMScript
v3.1.0 (2016-09-03)
-------------------
[new] Added option wrapper (Alizain Feerasta)
v3.0.1 (2016-07-20)
-------------------
Initial release

View File

@ -0,0 +1,9 @@
MIT License
Copyright (c) 2014-2021 Patrik Simek and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,397 @@
# vm2 [![NPM Version][npm-image]][npm-url] [![NPM Downloads][downloads-image]][downloads-url] [![Package Quality][quality-image]][quality-url] [![Travis CI][travis-image]][travis-url] [![Known Vulnerabilities][snyk-image]][snyk-url]
vm2 is a sandbox that can run untrusted code with whitelisted Node's built-in modules. Securely!
**Features**
* Runs untrusted code securely in a single process with your code side by side
* Full control over sandbox's console output
* Sandbox has limited access to process's methods
* Sandbox can require modules (builtin and external)
* You can limit access to certain (or all) builtin modules
* You can securely call methods and exchange data and callbacks between sandboxes
* Is immune to all known methods of attacks
* Transpilers support
**How does it work**
* It uses internal VM module to create secure context
* It uses [Proxies](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Proxy) to prevent escaping the sandbox
* It overrides builtin require to control access to modules
**What is the difference between Node's vm and vm2?**
Try it yourself:
```javascript
const vm = require('vm');
vm.runInNewContext('this.constructor.constructor("return process")().exit()');
console.log('Never gets executed.');
```
```javascript
const {VM} = require('vm2');
new VM().run('this.constructor.constructor("return process")().exit()');
// Throws ReferenceError: process is not defined
```
## Installation
**IMPORTANT**: Requires Node.js 6 or newer.
npm install vm2
## Quick Example
```javascript
const {VM} = require('vm2');
const vm = new VM();
vm.run(`process.exit()`); // TypeError: process.exit is not a function
```
```javascript
const {NodeVM} = require('vm2');
const vm = new NodeVM({
require: {
external: true
}
});
vm.run(`
var request = require('request');
request('http://www.google.com', function (error, response, body) {
console.error(error);
if (!error && response.statusCode == 200) {
console.log(body) // Show the HTML for the Google homepage.
}
})
`, 'vm.js');
```
## Documentation
* [VM](#vm)
* [NodeVM](#nodevm)
* [VMScript](#vmscript)
* [Error handling](#error-handling)
* [Debugging a sandboxed code](#debugging-a-sandboxed-code)
* [Read-only objects](#read-only-objects-experimental)
* [Protected objects](#protected-objects-experimental)
* [Cross-sandbox relationships](#cross-sandbox-relationships)
* [CLI](#cli)
* [2.x to 3.x changes](https://github.com/patriksimek/vm2/wiki/2.x-to-3.x-changes)
* [1.x and 2.x docs](https://github.com/patriksimek/vm2/wiki/1.x-and-2.x-docs)
* [Contributing](https://github.com/patriksimek/vm2/wiki/Contributing)
## VM
VM is a simple sandbox, without `require` feature, to synchronously run an untrusted code. Only JavaScript built-in objects + Buffer are available. Scheduling functions (`setInterval`, `setTimeout` and `setImmediate`) are not available by default.
**Options:**
* `timeout` - Script timeout in milliseconds.
* `sandbox` - VM's global object.
* `compiler` - `javascript` (default) or `coffeescript` or custom compiler function. The library expects you to have coffee-script pre-installed if the compiler is set to `coffeescript`.
* `eval` - If set to `false` any calls to `eval` or function constructors (`Function`, `GeneratorFunction`, etc) will throw an `EvalError` (default: `true`).
* `wasm` - If set to `false` any attempt to compile a WebAssembly module will throw a `WebAssembly.CompileError` (default: `true`).
* `fixAsync` - If set to `true` any attempt to run code using async will throw a `VMError` (default: `false`).
**IMPORTANT**: Timeout is only effective on synchronous code you run through `run`. Timeout is NOT effective on any method returned by VM. There're some situations when timeout doesn't work - see [#244](https://github.com/patriksimek/vm2/pull/244).
```javascript
const {VM} = require('vm2');
const vm = new VM({
timeout: 1000,
sandbox: {}
});
vm.run("process.exit()"); // throws ReferenceError: process is not defined
```
You can also retrieve values from VM.
```javascript
let number = vm.run("1337"); // returns 1337
```
**TIP**: See tests for more usage examples.
## NodeVM
Unlike `VM`, `NodeVM` lets you require modules same way like in regular Node's context.
**Options:**
* `console` - `inherit` to enable console, `redirect` to redirect to events, `off` to disable console (default: `inherit`).
* `sandbox` - VM's global object.
* `compiler` - `javascript` (default) or `coffeescript` or custom compiler function (which receives the code, and it's filepath). The library expects you to have coffee-script pre-installed if the compiler is set to `coffeescript`.
* `eval` - If set to `false` any calls to `eval` or function constructors (`Function`, `GeneratorFunction`, etc) will throw an `EvalError` (default: `true`).
* `wasm` - If set to `false` any attempt to compile a WebAssembly module will throw a `WebAssembly.CompileError` (default: `true`).
* `sourceExtensions` - Array of file extensions to treat as source code (default: `['js']`).
* `require` - `true` or object to enable `require` method (default: `false`).
* `require.external` - `true`, an array of allowed external modules or an object (default: `false`).
* `require.external.modules` - Array of allowed external modules. Also supports wildcards, so specifying `['@scope/*-ver-??]`, for instance, will allow using all modules having a name of the form `@scope/something-ver-aa`, `@scope/other-ver-11`, etc.
* `require.external.transitive` - Boolean which indicates if transitive dependencies of external modules are allowed (default: `false`).
* `require.builtin` - Array of allowed builtin modules, accepts ["*"] for all (default: none).
* `require.root` - Restricted path(s) where local modules can be required (default: every path).
* `require.mock` - Collection of mock modules (both external or builtin).
* `require.context` - `host` (default) to require modules in host and proxy them to sandbox. `sandbox` to load, compile and require modules in sandbox. Builtin modules except `events` always required in host and proxied to sandbox.
* `require.import` - Array of modules to be loaded into NodeVM on start.
* `require.resolve` - An additional lookup function in case a module wasn't found in one of the traditional node lookup paths.
* `nesting` - `true` to enable VMs nesting (default: `false`).
* `wrapper` - `commonjs` (default) to wrap script into CommonJS wrapper, `none` to retrieve value returned by the script.
* `argv` - Array to be passed to `process.argv`.
* `env` - Object to be passed to `process.env`.
* `strict` - `true` to loaded modules in strict mode (default: `false`).
**IMPORTANT**: Timeout is not effective for NodeVM so it is not immune to `while (true) {}` or similar evil.
**REMEMBER**: The more modules you allow, the more fragile your sandbox becomes.
```javascript
const {NodeVM} = require('vm2');
const vm = new NodeVM({
console: 'inherit',
sandbox: {},
require: {
external: true,
builtin: ['fs', 'path'],
root: "./",
mock: {
fs: {
readFileSync() { return 'Nice try!'; }
}
}
}
});
// Sync
let functionInSandbox = vm.run("module.exports = function(who) { console.log('hello '+ who); }");
functionInSandbox('world');
// Async
let functionWithCallbackInSandbox = vm.run("module.exports = function(who, callback) { callback('hello '+ who); }");
functionWithCallbackInSandbox('world', (greeting) => {
console.log(greeting);
});
```
When `wrapper` is set to `none`, `NodeVM` behaves more like `VM` for synchronous code.
```javascript
assert.ok(vm.run('return true') === true);
```
**TIP**: See tests for more usage examples.
### Loading modules by relative path
To load modules by relative path, you must pass full path of the script you're running as a second argument of vm's `run` method if the script is a string. Filename then also shows up in any stack traces produced from the script.
```javascript
vm.run("require('foobar')", "/data/myvmscript.js");
```
If the script you are running is an VMScript, the path is given in the VMScript constructor.
```javascript
const script = new VMScript("require('foobar')", {filename: "/data/myvmscript.js"});
vm.run(script);
```
## VMScript
You can increase performance by using pre-compiled scripts. The pre-compiled VMScript can be run later multiple times. It is important to note that the code is not bound to any VM (context); rather, it is bound before each run, just for that run.
```javascript
const {VM, VMScript} = require('vm2');
const vm = new VM();
const script = new VMScript("Math.random()");
console.log(vm.run(script));
console.log(vm.run(script));
```
Works for both `VM` and `NodeVM`.
```javascript
const {NodeVM, VMScript} = require('vm2');
const vm = new NodeVM();
const script = new VMScript("module.exports = Math.random()");
console.log(vm.run(script));
console.log(vm.run(script));
```
Code is compiled automatically first time you run it. You can compile the code anytime with `script.compile()`. Once the code is compiled, the method has no effect.
## Error handling
Errors in code compilation and synchronous code execution can be handled by `try`/`catch`. Errors in asynchronous code execution can be handled by attaching `uncaughtException` event handler to Node's `process`.
```javascript
try {
var script = new VMScript("Math.random()").compile();
} catch (err) {
console.error('Failed to compile script.', err);
}
try {
vm.run(script);
} catch (err) {
console.error('Failed to execute script.', err);
}
process.on('uncaughtException', (err) => {
console.error('Asynchronous error caught.', err);
})
```
## Debugging a sandboxed code
You can debug/inspect code running in the sandbox as if it was running in a normal process.
- You can use breakpoints (requires you to specify a script file name)
- You can use `debugger` keyword.
- You can use step-in to step inside the code running in the sandbox.
**Example**
/tmp/main.js:
```javascript
const {VM, VMScript} = require('.');
const fs = require('fs');
const file = `${__dirname}/sandbox.js`;
// By providing a file name as second argument you enable breakpoints
const script = new VMScript(fs.readFileSync(file), file);
new VM().run(script);
```
/tmp/sandbox.js
```javascript
const foo = 'ahoj';
// Debugger keyword works just fine anywhere.
// Even without specifying a file name to the VMScript object.
debugger;
```
## Read-only objects (experimental)
To prevent sandboxed script to add/change/delete properties to/from the proxied objects, you can use `freeze` methods to make the object read-only. This is only effective inside VM. Frozen objects are affected deeply. Primitive types can not be frozen.
**Example without using `freeze`:**
```javascript
const util = {
add: (a, b) => a + b
}
const vm = new VM({
sandbox: {util}
});
vm.run('util.add = (a, b) => a - b');
console.log(util.add(1, 1)); // returns 0
```
**Example with using `freeze`:**
```javascript
const vm = new VM(); // Objects specified in sandbox can not be frozen.
vm.freeze(util, 'util'); // Second argument adds object to global.
vm.run('util.add = (a, b) => a - b'); // Fails silently when not in strict mode.
console.log(util.add(1, 1)); // returns 2
```
**IMPORTANT:** It is not possible to freeze objects that has already been proxied to the VM.
## Protected objects (experimental)
Unlike `freeze`, this method allows sandboxed script to add/modify/delete properties on object with one exception - it is not possible to attach functions. Sandboxed script is therefore not able to modify methods like `toJSON`, `toString` or `inspect`.
**IMPORTANT:** It is not possible to protect objects that has already been proxied to the VM.
## Cross-sandbox relationships
```javascript
const assert = require('assert');
const {VM} = require('vm2');
const sandbox = {
object: new Object(),
func: new Function(),
buffer: new Buffer([0x01, 0x05])
}
const vm = new VM({sandbox});
assert.ok(vm.run(`object`) === sandbox.object);
assert.ok(vm.run(`object instanceof Object`));
assert.ok(vm.run(`object`) instanceof Object);
assert.ok(vm.run(`object.__proto__ === Object.prototype`));
assert.ok(vm.run(`object`).__proto__ === Object.prototype);
assert.ok(vm.run(`func`) === sandbox.func);
assert.ok(vm.run(`func instanceof Function`));
assert.ok(vm.run(`func`) instanceof Function);
assert.ok(vm.run(`func.__proto__ === Function.prototype`));
assert.ok(vm.run(`func`).__proto__ === Function.prototype);
assert.ok(vm.run(`new func() instanceof func`));
assert.ok(vm.run(`new func()`) instanceof sandbox.func);
assert.ok(vm.run(`new func().__proto__ === func.prototype`));
assert.ok(vm.run(`new func()`).__proto__ === sandbox.func.prototype);
assert.ok(vm.run(`buffer`) === sandbox.buffer);
assert.ok(vm.run(`buffer instanceof Buffer`));
assert.ok(vm.run(`buffer`) instanceof Buffer);
assert.ok(vm.run(`buffer.__proto__ === Buffer.prototype`));
assert.ok(vm.run(`buffer`).__proto__ === Buffer.prototype);
assert.ok(vm.run(`buffer.slice(0, 1) instanceof Buffer`));
assert.ok(vm.run(`buffer.slice(0, 1)`) instanceof Buffer);
```
## CLI
Before you can use vm2 in command line, install it globally with `npm install vm2 -g`.
```
$ vm2 ./script.js
```
## Known Issues
* It is not possible to define class that extends proxied class.
## Deployment
1. Update the CHANGELOG
2. Update the `package.json` version number
3. Commit the changes
4. Run `npm publish`
## Sponsors
[![Integromat][integromat-image]][integromat-url]
[npm-image]: https://img.shields.io/npm/v/vm2.svg?style=flat-square
[npm-url]: https://www.npmjs.com/package/vm2
[downloads-image]: https://img.shields.io/npm/dm/vm2.svg?style=flat-square
[downloads-url]: https://www.npmjs.com/package/vm2
[quality-image]: http://npm.packagequality.com/shield/vm2.svg?style=flat-square
[quality-url]: http://packagequality.com/#?package=vm2
[travis-image]: https://img.shields.io/travis/patriksimek/vm2/master.svg?style=flat-square&label=unit
[travis-url]: https://travis-ci.org/patriksimek/vm2
[snyk-image]: https://snyk.io/test/github/patriksimek/vm2/badge.svg
[snyk-url]: https://snyk.io/test/github/patriksimek/vm2
[integromat-image]: https://static.integromat.com/logo/45_text.png
[integromat-url]: https://www.integromat.com

View File

@ -0,0 +1,3 @@
#!/usr/bin/env node
require(__dirname +'/../lib/cli.js');

198
src/assets/plugins/vm2/index.d.ts vendored Normal file
View File

@ -0,0 +1,198 @@
import {EventEmitter} from 'events';
/**
* Require options for a VM
*/
export interface VMRequire {
/** Array of allowed builtin modules, accepts ["*"] for all (default: none) */
builtin?: string[];
/*
* `host` (default) to require modules in host and proxy them to sandbox. `sandbox` to load, compile and
* require modules in sandbox. Builtin modules except `events` always required in host and proxied to sandbox
*/
context?: "host" | "sandbox";
/** `true`, an array of allowed external modules or an object with external options (default: `false`) */
external?: boolean | string[] | { modules: string[], transitive: boolean };
/** Array of modules to be loaded into NodeVM on start. */
import?: string[];
/** Restricted path(s) where local modules can be required (default: every path). */
root?: string | string[];
/** Collection of mock modules (both external or builtin). */
mock?: any;
/* An additional lookup function in case a module wasn't found in one of the traditional node lookup paths. */
resolve?: (moduleName: string, parentDirname: string) => string;
}
/**
* A custom compiler function for all of the JS that comes
* into the VM
*/
type CompilerFunction = (code: string, filename: string) => string;
/**
* Options for creating a VM
*/
export interface VMOptions {
/**
* `javascript` (default) or `coffeescript` or custom compiler function (which receives the code, and it's filepath).
* The library expects you to have coffee-script pre-installed if the compiler is set to `coffeescript`.
*/
compiler?: "javascript" | "coffeescript" | CompilerFunction;
/** VM's global object. */
sandbox?: any;
/**
* Script timeout in milliseconds. Timeout is only effective on code you run through `run`.
* Timeout is NOT effective on any method returned by VM.
*/
timeout?: number;
/**
* If set to `false` any calls to eval or function constructors (`Function`, `GeneratorFunction`, etc) will throw an
* `EvalError` (default: `true`).
*/
eval?: boolean;
/**
* If set to `false` any attempt to compile a WebAssembly module will throw a `WebAssembly.CompileError` (default: `true`).
*/
wasm?: boolean;
/**
* If set to `true` any attempt to run code using async will throw a `VMError` (default: `false`).
*/
fixAsync?: boolean;
}
/**
* Options for creating a NodeVM
*/
export interface NodeVMOptions extends VMOptions {
/** `inherit` to enable console, `redirect` to redirect to events, `off` to disable console (default: `inherit`). */
console?: "inherit" | "redirect" | "off";
/** `true` or an object to enable `require` options (default: `false`). */
require?: true | VMRequire;
/** `true` to enable VMs nesting (default: `false`). */
nesting?: boolean;
/** `commonjs` (default) to wrap script into CommonJS wrapper, `none` to retrieve value returned by the script. */
wrapper?: "commonjs" | "none";
/** File extensions that the internal module resolver should accept. */
sourceExtensions?: string[];
/**
* Array of arguments passed to `process.argv`.
* This object will not be copied and the script can change this object.
*/
argv?: string[];
/**
* Environment map passed to `process.env`.
* This object will not be copied and the script can change this object.
*/
env?: any;
}
/**
* VM is a simple sandbox, without `require` feature, to synchronously run an untrusted code.
* Only JavaScript built-in objects + Buffer are available. Scheduling functions
* (`setInterval`, `setTimeout` and `setImmediate`) are not available by default.
*/
export class VM {
constructor(options?: VMOptions);
/** Direct access to the global sandbox object */
readonly sandbox: any;
/** Timeout to use for the run methods */
timeout?: number;
/** Runs the code */
run(js: string, path?: string): any;
/** Runs the VMScript object */
run(script: VMScript): any;
/** Runs the code in the specific file */
runFile(filename: string): any;
/** Loads all the values into the global object with the same names */
setGlobals(values: any): this;
/** Make a object visible as a global with a specific name */
setGlobal(name: string, value: any): this;
/** Get the global object with the specific name */
getGlobal(name: string): any;
/** Freezes the object inside VM making it read-only. Not available for primitive values. */
freeze(object: any, name?: string): any;
/** Protects the object inside VM making impossible to set functions as it's properties. Not available for primitive values */
protect(object: any, name?: string): any;
}
/**
* A VM with behavior more similar to running inside Node.
*/
export class NodeVM extends EventEmitter implements VM {
constructor(options?: NodeVMOptions);
/** Require a module in VM and return it's exports. */
require(module: string): any;
/**
* Create NodeVM and run code inside it.
*
* @param {string} script Javascript code.
* @param {string} [filename] File name (used in stack traces only).
* @param {Object} [options] VM options.
*/
static code(script: string, filename?: string, options?: NodeVMOptions): any;
/**
* Create NodeVM and run script from file inside it.
*
* @param {string} [filename] File name (used in stack traces only).
* @param {Object} [options] VM options.
*/
static file(filename: string, options?: NodeVMOptions): any;
/** Direct access to the global sandbox object */
readonly sandbox: any;
/** Only here because of implements VM. Does nothing. */
timeout?: number;
/** Runs the code */
run(js: string, path?: string): any;
/** Runs the VMScript object */
run(script: VMScript): any;
/** Runs the code in the specific file */
runFile(filename: string): any;
/** Loads all the values into the global object with the same names */
setGlobals(values: any): this;
/** Make a object visible as a global with a specific name */
setGlobal(name: string, value: any): this;
/** Get the global object with the specific name */
getGlobal(name: string): any;
/** Freezes the object inside VM making it read-only. Not available for primitive values. */
freeze(object: any, name?: string): any;
/** Protects the object inside VM making impossible to set functions as it's properties. Not available for primitive values */
protect(object: any, name?: string): any;
}
/**
* You can increase performance by using pre-compiled scripts.
* The pre-compiled VMScript can be run later multiple times. It is important to note that the code is not bound
* to any VM (context); rather, it is bound before each run, just for that run.
*/
export class VMScript {
constructor(code: string, path: string, options?: {
lineOffset?: number;
columnOffset?: number;
compiler?: "javascript" | "coffeescript" | CompilerFunction;
});
constructor(code: string, options?: {
filename?: string,
lineOffset?: number;
columnOffset?: number;
compiler?: "javascript" | "coffeescript" | CompilerFunction;
});
readonly code: string;
readonly filename: string;
readonly lineOffset: number;
readonly columnOffset: number;
readonly compiler: "javascript" | "coffeescript" | CompilerFunction;
/**
* Wraps the code
* @deprecated
*/
wrap(prefix: string, postfix: string): this;
/** Compiles the code. If called multiple times, the code is only compiled once. */
compile(): this;
}
/** Custom Error class */
export class VMError extends Error {}

View File

@ -0,0 +1,3 @@
if (parseInt(process.versions.node.split('.')[0]) < 6) throw new Error('vm2 requires Node.js version 6 or newer.');
module.exports = require('./lib/main');

View File

@ -0,0 +1,35 @@
'use strict';
const pa = require('path');
const {NodeVM, VMError} = require('../');
if (process.argv[2]) {
const path = pa.resolve(process.argv[2]);
console.log(`\x1B[90m[vm] creating VM for ${path}\x1B[39m`);
const started = Date.now();
try {
NodeVM.file(path, {
verbose: true,
require: {
external: true
}
});
console.log(`\x1B[90m[vm] VM completed in ${Date.now() - started}ms\x1B[39m`);
} catch (ex) {
if (ex instanceof VMError) {
console.error(`\x1B[31m[vm:error] ${ex.message}\x1B[39m`);
} else {
const {stack} = ex;
if (stack) {
console.error(`\x1B[31m[vm:error] ${stack}\x1B[39m`);
} else {
console.error(`\x1B[31m[vm:error] ${ex}\x1B[39m`);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,83 @@
'use strict';
// eslint-disable-next-line no-invalid-this, no-shadow
const {GeneratorFunction, AsyncFunction, AsyncGeneratorFunction, global, internal, host, hook} = this;
const {Contextify, Decontextify} = internal;
// eslint-disable-next-line no-shadow
const {Function, eval: eval_, Promise, Object, Reflect} = global;
const {getOwnPropertyDescriptor, defineProperty, assign} = Object;
const {apply: rApply, construct: rConstruct} = Reflect;
const FunctionHandler = {
__proto__: null,
apply(target, thiz, args) {
const type = this.type;
args = Decontextify.arguments(args);
try {
args = Contextify.value(hook(type, args));
} catch (e) {
throw Contextify.value(e);
}
return rApply(target, thiz, args);
},
construct(target, args, newTarget) {
const type = this.type;
args = Decontextify.arguments(args);
try {
args = Contextify.value(hook(type, args));
} catch (e) {
throw Contextify.value(e);
}
return rConstruct(target, args, newTarget);
}
};
function makeCheckFunction(type) {
return assign({
__proto__: null,
type
}, FunctionHandler);
}
function override(obj, prop, value) {
const desc = getOwnPropertyDescriptor(obj, prop);
desc.value = value;
defineProperty(obj, prop, desc);
}
const proxiedFunction = new host.Proxy(Function, makeCheckFunction('function'));
override(Function.prototype, 'constructor', proxiedFunction);
if (GeneratorFunction) {
Object.setPrototypeOf(GeneratorFunction, proxiedFunction);
override(GeneratorFunction.prototype, 'constructor', new host.Proxy(GeneratorFunction, makeCheckFunction('generator_function')));
}
if (AsyncFunction) {
Object.setPrototypeOf(AsyncFunction, proxiedFunction);
override(AsyncFunction.prototype, 'constructor', new host.Proxy(AsyncFunction, makeCheckFunction('async_function')));
}
if (AsyncGeneratorFunction) {
Object.setPrototypeOf(AsyncGeneratorFunction, proxiedFunction);
override(AsyncGeneratorFunction.prototype, 'constructor', new host.Proxy(AsyncGeneratorFunction, makeCheckFunction('async_generator_function')));
}
global.Function = proxiedFunction;
global.eval = new host.Proxy(eval_, makeCheckFunction('eval'));
if (Promise) {
Promise.prototype.then = new host.Proxy(Promise.prototype.then, makeCheckFunction('promise_then'));
// This seems not to work, and will produce
// UnhandledPromiseRejectionWarning: TypeError: Method Promise.prototype.then called on incompatible receiver [object Object].
// This is likely caused since the host.Promise.prototype.then cannot use the VM Proxy object.
// Contextify.connect(host.Promise.prototype.then, Promise.prototype.then);
if (Promise.prototype.finally) {
Promise.prototype.finally = new host.Proxy(Promise.prototype.finally, makeCheckFunction('promise_finally'));
// Contextify.connect(host.Promise.prototype.finally, Promise.prototype.finally);
}
if (Promise.prototype.catch) {
Promise.prototype.catch = new host.Proxy(Promise.prototype.catch, makeCheckFunction('promise_catch'));
// Contextify.connect(host.Promise.prototype.catch, Promise.prototype.catch);
}
}

View File

@ -0,0 +1,12 @@
// source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping
function escapeRegExp(string) {
return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
function match(wildcard, s) {
const regexString = escapeRegExp(wildcard).replace(/\\\*/g, '\\S*').replace(/\\\?/g, '.');
const regex = new RegExp(regexString);
return regex.test(s);
}
module.exports = {match};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,682 @@
/* eslint-disable no-shadow, no-invalid-this */
/* global vm, host, Contextify, Decontextify, VMError, options */
'use strict';
const {Script} = host.require('vm');
const fs = host.require('fs');
const pa = host.require('path');
const BUILTIN_MODULES = host.process.binding('natives');
const parseJSON = JSON.parse;
const importModuleDynamically = () => {
// We can't throw an error object here because since vm.Script doesn't store a context, we can't properly contextify that error object.
// eslint-disable-next-line no-throw-literal
throw 'Dynamic imports are not allowed.';
};
/**
* @param {Object} host Hosts's internal objects.
*/
return ((vm, host) => {
'use strict';
const global = this;
const TIMERS = new host.WeakMap(); // Contains map of timers created inside sandbox
const BUILTINS = {__proto__: null};
const CACHE = {__proto__: null};
const EXTENSIONS = {
__proto__: null,
['.json'](module, filename) {
try {
const code = fs.readFileSync(filename, 'utf8');
module.exports = parseJSON(code);
} catch (e) {
throw Contextify.value(e);
}
},
['.node'](module, filename) {
if (vm.options.require.context === 'sandbox') throw new VMError('Native modules can be required only with context set to \'host\'.');
try {
module.exports = Contextify.readonly(host.require(filename));
} catch (e) {
throw Contextify.value(e);
}
}
};
for (let i = 0; i < vm.options.sourceExtensions.length; i++) {
const ext = vm.options.sourceExtensions[i];
EXTENSIONS['.' + ext] = (module, filename, dirname) => {
if (vm.options.require.context !== 'sandbox') {
try {
module.exports = Contextify.readonly(host.require(filename));
} catch (e) {
throw Contextify.value(e);
}
} else {
let script;
try {
// Load module
let contents = fs.readFileSync(filename, 'utf8');
contents = vm._compiler(contents, filename);
const code = host.STRICT_MODULE_PREFIX + contents + host.MODULE_SUFFIX;
const ccode = vm._hook('run', [code]);
// Precompile script
script = new Script(ccode, {
__proto__: null,
filename: filename || 'vm.js',
displayErrors: false,
importModuleDynamically
});
} catch (ex) {
throw Contextify.value(ex);
}
const closure = script.runInContext(global, {
__proto__: null,
filename: filename || 'vm.js',
displayErrors: false,
importModuleDynamically
});
// run the script
closure(module.exports, module.require, module, filename, dirname);
}
};
}
const _parseExternalOptions = (options) => {
if (host.Array.isArray(options)) {
return {
__proto__: null,
external: options,
transitive: false
};
}
return {
__proto__: null,
external: options.modules,
transitive: options.transitive
};
};
/**
* Resolve filename.
*/
const _resolveFilename = (path) => {
if (!path) return null;
let hasPackageJson;
try {
path = pa.resolve(path);
const exists = fs.existsSync(path);
const isdir = exists ? fs.statSync(path).isDirectory() : false;
// direct file match
if (exists && !isdir) return path;
// load as file
for (let i = 0; i < vm.options.sourceExtensions.length; i++) {
const ext = vm.options.sourceExtensions[i];
if (fs.existsSync(`${path}.${ext}`)) return `${path}.${ext}`;
}
if (fs.existsSync(`${path}.json`)) return `${path}.json`;
if (fs.existsSync(`${path}.node`)) return `${path}.node`;
// load as module
hasPackageJson = fs.existsSync(`${path}/package.json`);
} catch (e) {
throw Contextify.value(e);
}
if (hasPackageJson) {
let pkg;
try {
pkg = fs.readFileSync(`${path}/package.json`, 'utf8');
} catch (e) {
throw Contextify.value(e);
}
try {
pkg = parseJSON(pkg);
} catch (ex) {
throw new VMError(`Module '${path}' has invalid package.json`, 'EMODULEINVALID');
}
let main;
if (pkg && pkg.main) {
main = _resolveFilename(`${path}/${pkg.main}`);
if (!main) main = _resolveFilename(`${path}/index`);
} else {
main = _resolveFilename(`${path}/index`);
}
return main;
}
// load as directory
try {
for (let i = 0; i < vm.options.sourceExtensions.length; i++) {
const ext = vm.options.sourceExtensions[i];
if (fs.existsSync(`${path}/index.${ext}`)) return `${path}/index.${ext}`;
}
if (fs.existsSync(`${path}/index.json`)) return `${path}/index.json`;
if (fs.existsSync(`${path}/index.node`)) return `${path}/index.node`;
} catch (e) {
throw Contextify.value(e);
}
return null;
};
/**
* Builtin require.
*/
const _requireBuiltin = (moduleName) => {
if (moduleName === 'buffer') return ({Buffer});
if (BUILTINS[moduleName]) return BUILTINS[moduleName].exports; // Only compiled builtins are stored here
if (moduleName === 'util') {
return Contextify.readonly(host.require(moduleName), {
// Allows VM context to use util.inherits
__proto__: null,
inherits: (ctor, superCtor) => {
ctor.super_ = superCtor;
Object.setPrototypeOf(ctor.prototype, superCtor.prototype);
}
});
}
if (moduleName === 'events' || moduleName === 'internal/errors') {
let script;
try {
script = new Script(`(function (exports, require, module, process, internalBinding) {
'use strict';
const primordials = global;
${BUILTIN_MODULES[moduleName]}
\n
});`, {
filename: `${moduleName}.vm.js`
});
} catch (e) {
throw Contextify.value(e);
}
// setup module scope
const module = BUILTINS[moduleName] = {
exports: {},
require: _requireBuiltin
};
// run script
try {
// FIXME binding should be contextified
script.runInContext(global)(module.exports, module.require, module, host.process, host.process.binding);
} catch (e) {
// e could be from inside or outside of sandbox
throw new VMError(`Error loading '${moduleName}'`);
}
return module.exports;
}
return Contextify.readonly(host.require(moduleName));
};
/**
* Prepare require.
*/
const _prepareRequire = (currentDirname, parentAllowsTransitive = false) => {
const _require = moduleName => {
let requireObj;
try {
const optionsObj = vm.options;
if (optionsObj.nesting && moduleName === 'vm2') return {VM: Contextify.readonly(host.VM), NodeVM: Contextify.readonly(host.NodeVM)};
requireObj = optionsObj.require;
} catch (e) {
throw Contextify.value(e);
}
if (!requireObj) throw new VMError(`Access denied to require '${moduleName}'`, 'EDENIED');
if (moduleName == null) throw new VMError("Module '' not found.", 'ENOTFOUND');
if (typeof moduleName !== 'string') throw new VMError(`Invalid module name '${moduleName}'`, 'EINVALIDNAME');
let filename;
let allowRequireTransitive = false;
// Mock?
try {
const {mock} = requireObj;
if (mock) {
const mockModule = mock[moduleName];
if (mockModule) {
return Contextify.readonly(mockModule);
}
}
} catch (e) {
throw Contextify.value(e);
}
// Builtin?
if (BUILTIN_MODULES[moduleName]) {
let allowed;
try {
const builtinObj = requireObj.builtin;
if (host.Array.isArray(builtinObj)) {
if (builtinObj.indexOf('*') >= 0) {
allowed = builtinObj.indexOf(`-${moduleName}`) === -1;
} else {
allowed = builtinObj.indexOf(moduleName) >= 0;
}
} else if (builtinObj) {
allowed = builtinObj[moduleName];
} else {
allowed = false;
}
} catch (e) {
throw Contextify.value(e);
}
if (!allowed) throw new VMError(`Access denied to require '${moduleName}'`, 'EDENIED');
return _requireBuiltin(moduleName);
}
// External?
let externalObj;
try {
externalObj = requireObj.external;
} catch (e) {
throw Contextify.value(e);
}
if (!externalObj) throw new VMError(`Access denied to require '${moduleName}'`, 'EDENIED');
if (/^(\.|\.\/|\.\.\/)/.exec(moduleName)) {
// Module is relative file, e.g. ./script.js or ../script.js
if (!currentDirname) throw new VMError('You must specify script path to load relative modules.', 'ENOPATH');
filename = _resolveFilename(`${currentDirname}/${moduleName}`);
} else if (/^(\/|\\|[a-zA-Z]:\\)/.exec(moduleName)) {
// Module is absolute file, e.g. /script.js or //server/script.js or C:\script.js
filename = _resolveFilename(moduleName);
} else {
// Check node_modules in path
if (!currentDirname) throw new VMError('You must specify script path to load relative modules.', 'ENOPATH');
if (typeof externalObj === 'object') {
let isWhitelisted;
try {
const { external, transitive } = _parseExternalOptions(externalObj);
isWhitelisted = external.some(ext => host.helpers.match(ext, moduleName)) || (transitive && parentAllowsTransitive);
} catch (e) {
throw Contextify.value(e);
}
if (!isWhitelisted) {
throw new VMError(`The module '${moduleName}' is not whitelisted in VM.`, 'EDENIED');
}
allowRequireTransitive = true;
}
// FIXME the paths array has side effects
const paths = currentDirname.split(pa.sep);
while (paths.length) {
const path = paths.join(pa.sep);
// console.log moduleName, "#{path}#{pa.sep}node_modules#{pa.sep}#{moduleName}"
filename = _resolveFilename(`${path}${pa.sep}node_modules${pa.sep}${moduleName}`);
if (filename) break;
paths.pop();
}
}
if (!filename) {
let resolveFunc;
try {
resolveFunc = requireObj.resolve;
} catch (e) {
throw Contextify.value(e);
}
if (resolveFunc) {
let resolved;
try {
resolved = requireObj.resolve(moduleName, currentDirname);
} catch (e) {
throw Contextify.value(e);
}
filename = _resolveFilename(resolved);
}
}
if (!filename) throw new VMError(`Cannot find module '${moduleName}'`, 'ENOTFOUND');
// return cache whenever possible
if (CACHE[filename]) return CACHE[filename].exports;
const dirname = pa.dirname(filename);
const extname = pa.extname(filename);
let allowedModule = true;
try {
const rootObj = requireObj.root;
if (rootObj) {
const rootPaths = host.Array.isArray(rootObj) ? rootObj : host.Array.of(rootObj);
allowedModule = rootPaths.some(path => host.String.prototype.startsWith.call(dirname, pa.resolve(path)));
}
} catch (e) {
throw Contextify.value(e);
}
if (!allowedModule) {
throw new VMError(`Module '${moduleName}' is not allowed to be required. The path is outside the border!`, 'EDENIED');
}
const module = CACHE[filename] = {
filename,
exports: {},
require: _prepareRequire(dirname, allowRequireTransitive)
};
// lookup extensions
if (EXTENSIONS[extname]) {
EXTENSIONS[extname](module, filename, dirname);
return module.exports;
}
throw new VMError(`Failed to load '${moduleName}': Unknown type.`, 'ELOADFAIL');
};
return _require;
};
/**
* Prepare sandbox.
*/
// This is a function and not an arrow function, since the original is also a function
global.setTimeout = function setTimeout(callback, delay, ...args) {
if (typeof callback !== 'function') throw new TypeError('"callback" argument must be a function');
let tmr;
try {
tmr = host.setTimeout(Decontextify.value(() => {
// FIXME ...args has side effects
callback(...args);
}), Decontextify.value(delay));
} catch (e) {
throw Contextify.value(e);
}
const local = Contextify.value(tmr);
TIMERS.set(local, tmr);
return local;
};
global.setInterval = function setInterval(callback, interval, ...args) {
if (typeof callback !== 'function') throw new TypeError('"callback" argument must be a function');
let tmr;
try {
tmr = host.setInterval(Decontextify.value(() => {
// FIXME ...args has side effects
callback(...args);
}), Decontextify.value(interval));
} catch (e) {
throw Contextify.value(e);
}
const local = Contextify.value(tmr);
TIMERS.set(local, tmr);
return local;
};
global.setImmediate = function setImmediate(callback, ...args) {
if (typeof callback !== 'function') throw new TypeError('"callback" argument must be a function');
let tmr;
try {
tmr = host.setImmediate(Decontextify.value(() => {
// FIXME ...args has side effects
callback(...args);
}));
} catch (e) {
throw Contextify.value(e);
}
const local = Contextify.value(tmr);
TIMERS.set(local, tmr);
return local;
};
global.clearTimeout = function clearTimeout(local) {
try {
host.clearTimeout(TIMERS.get(local));
} catch (e) {
throw Contextify.value(e);
}
};
global.clearInterval = function clearInterval(local) {
try {
host.clearInterval(TIMERS.get(local));
} catch (e) {
throw Contextify.value(e);
}
};
global.clearImmediate = function clearImmediate(local) {
try {
host.clearImmediate(TIMERS.get(local));
} catch (e) {
throw Contextify.value(e);
}
};
function addListener(name, handler) {
if (name !== 'beforeExit' && name !== 'exit') {
throw new Error(`Access denied to listen for '${name}' event.`);
}
try {
host.process.on(name, Decontextify.value(handler));
} catch (e) {
throw Contextify.value(e);
}
return this;
}
const {argv: optionArgv, env: optionsEnv} = options;
// FIXME wrong class structure
global.process = {
argv: optionArgv !== undefined ? Contextify.value(optionArgv) : [],
title: host.process.title,
version: host.process.version,
versions: Contextify.readonly(host.process.versions),
arch: host.process.arch,
platform: host.process.platform,
env: optionsEnv !== undefined ? Contextify.value(optionsEnv) : {},
pid: host.process.pid,
features: Contextify.readonly(host.process.features),
nextTick: function nextTick(callback, ...args) {
if (typeof callback !== 'function') {
throw new Error('Callback must be a function.');
}
try {
host.process.nextTick(Decontextify.value(() => {
// FIXME ...args has side effects
callback(...args);
}));
} catch (e) {
throw Contextify.value(e);
}
},
hrtime: function hrtime(time) {
try {
return Contextify.value(host.process.hrtime(Decontextify.value(time)));
} catch (e) {
throw Contextify.value(e);
}
},
cwd: function cwd() {
try {
return Contextify.value(host.process.cwd());
} catch (e) {
throw Contextify.value(e);
}
},
addListener,
on: addListener,
once: function once(name, handler) {
if (name !== 'beforeExit' && name !== 'exit') {
throw new Error(`Access denied to listen for '${name}' event.`);
}
try {
host.process.once(name, Decontextify.value(handler));
} catch (e) {
throw Contextify.value(e);
}
return this;
},
listeners: function listeners(name) {
if (name !== 'beforeExit' && name !== 'exit') {
// Maybe add ({__proto__:null})[name] to throw when name fails in https://tc39.es/ecma262/#sec-topropertykey.
return [];
}
// Filter out listeners, which were not created in this sandbox
try {
return Contextify.value(host.process.listeners(name).filter(listener => Contextify.isVMProxy(listener)));
} catch (e) {
throw Contextify.value(e);
}
},
removeListener: function removeListener(name, handler) {
if (name !== 'beforeExit' && name !== 'exit') {
return this;
}
try {
host.process.removeListener(name, Decontextify.value(handler));
} catch (e) {
throw Contextify.value(e);
}
return this;
},
umask: function umask() {
if (arguments.length) {
throw new Error('Access denied to set umask.');
}
try {
return Contextify.value(host.process.umask());
} catch (e) {
throw Contextify.value(e);
}
}
};
if (vm.options.console === 'inherit') {
global.console = Contextify.readonly(host.console);
} else if (vm.options.console === 'redirect') {
global.console = {
debug(...args) {
try {
// FIXME ...args has side effects
vm.emit('console.debug', ...Decontextify.arguments(args));
} catch (e) {
throw Contextify.value(e);
}
},
log(...args) {
try {
// FIXME ...args has side effects
vm.emit('console.log', ...Decontextify.arguments(args));
} catch (e) {
throw Contextify.value(e);
}
},
info(...args) {
try {
// FIXME ...args has side effects
vm.emit('console.info', ...Decontextify.arguments(args));
} catch (e) {
throw Contextify.value(e);
}
},
warn(...args) {
try {
// FIXME ...args has side effects
vm.emit('console.warn', ...Decontextify.arguments(args));
} catch (e) {
throw Contextify.value(e);
}
},
error(...args) {
try {
// FIXME ...args has side effects
vm.emit('console.error', ...Decontextify.arguments(args));
} catch (e) {
throw Contextify.value(e);
}
},
dir(...args) {
try {
vm.emit('console.dir', ...Decontextify.arguments(args));
} catch (e) {
throw Contextify.value(e);
}
},
time() {},
timeEnd() {},
trace(...args) {
try {
// FIXME ...args has side effects
vm.emit('console.trace', ...Decontextify.arguments(args));
} catch (e) {
throw Contextify.value(e);
}
}
};
}
/*
Return contextified require.
*/
return _prepareRequire;
})(vm, host);

View File

@ -0,0 +1,37 @@
{
"author": {
"name": "Patrik Simek",
"url": "https://patriksimek.cz"
},
"name": "vm2",
"description": "vm2 is a sandbox that can run untrusted code with whitelisted Node's built-in modules. Securely!",
"keywords": [
"sandbox",
"prison",
"jail",
"vm",
"alcatraz",
"contextify"
],
"version": "3.9.5",
"main": "index.js",
"repository": "github:patriksimek/vm2",
"license": "MIT",
"dependencies": {},
"devDependencies": {
"eslint": "^5.16.0",
"eslint-config-integromat": "^1.5.0",
"mocha": "^6.2.2"
},
"engines": {
"node": ">=6.0"
},
"scripts": {
"test": "mocha test",
"pretest": "eslint ."
},
"bin": {
"vm2": "./bin/vm2"
},
"types": "index.d.ts"
}

156
src/package-lock.json generated
View File

@ -1,62 +1,140 @@
{
"name": "src",
"lockfileVersion": 2,
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"axios": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz",
"integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==",
"requires": {
"follow-redirects": "1.5.10"
"packages": {
"": {
"dependencies": {
"axios": "^0.24.0",
"iconv-lite": "^0.6.3",
"pinyin-match": "^1.2.2",
"solarlunar": "^2.0.7"
}
},
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"node_modules/axios": {
"version": "0.24.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz",
"integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==",
"dependencies": {
"follow-redirects": "^1.14.4"
}
},
"node_modules/follow-redirects": {
"version": "1.14.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.6.tgz",
"integrity": "sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/pinyin-match": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/pinyin-match/-/pinyin-match-1.2.2.tgz",
"integrity": "sha512-C0yOq4LkToJMkDHiQFKOY69El2GRcwdS2lVEjgWjIV8go3wE4mloGFNkVicGHFGYHDg523m2/lKzW8Hh+JR9nw==",
"dependencies": {
"rollup": "^2.44.0"
}
},
"node_modules/rollup": {
"version": "2.63.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.63.0.tgz",
"integrity": "sha512-nps0idjmD+NXl6OREfyYXMn/dar3WGcyKn+KBzPdaLecub3x/LrId0wUcthcr8oZUAcZAR8NKcfGGFlNgGL1kQ==",
"bin": {
"rollup": "dist/bin/rollup"
},
"engines": {
"node": ">=10.0.0"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
}
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"node_modules/solarlunar": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/solarlunar/-/solarlunar-2.0.7.tgz",
"integrity": "sha512-2SfuCCgAAxFU5MTMYuKGbRgRLcPTJQf3azMEw/GmBpHXA7N2eAQJStSqktZJjnq4qRCboBPnqEB866+PCregag=="
}
},
"dependencies": {
"axios": {
"version": "0.24.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz",
"integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==",
"requires": {
"ms": "2.0.0"
"follow-redirects": "^1.14.4"
}
},
"follow-redirects": {
"version": "1.5.10",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
"integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
"requires": {
"debug": "=3.1.0"
}
"version": "1.14.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.6.tgz",
"integrity": "sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A=="
},
"fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmmirror.com/fsevents/download/fsevents-2.3.2.tgz",
"integrity": "sha1-ilJveLj99GI7cJ4Ll1xSwkwC/Ro=",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"optional": true
},
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
"safer-buffer": ">= 2.1.2 < 3.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"pinyin-match": {
"version": "1.2.2",
"resolved": "https://registry.npmmirror.com/pinyin-match/download/pinyin-match-1.2.2.tgz",
"integrity": "sha1-JKYKW86J+ykD8z83SSeC0/jjTus=",
"resolved": "https://registry.npmjs.org/pinyin-match/-/pinyin-match-1.2.2.tgz",
"integrity": "sha512-C0yOq4LkToJMkDHiQFKOY69El2GRcwdS2lVEjgWjIV8go3wE4mloGFNkVicGHFGYHDg523m2/lKzW8Hh+JR9nw==",
"requires": {
"rollup": "^2.44.0"
}
},
"rollup": {
"version": "2.62.0",
"resolved": "https://registry.npmmirror.com/rollup/download/rollup-2.62.0.tgz",
"integrity": "sha512-cJEQq2gwB0GWMD3rYImefQTSjrPYaC6s4J9pYqnstVLJ1CHa/aZNVkD4Epuvg4iLeMA4KRiq7UM7awKK6j7jcw==",
"version": "2.63.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.63.0.tgz",
"integrity": "sha512-nps0idjmD+NXl6OREfyYXMn/dar3WGcyKn+KBzPdaLecub3x/LrId0wUcthcr8oZUAcZAR8NKcfGGFlNgGL1kQ==",
"requires": {
"fsevents": "~2.3.2"
}
@ -66,10 +144,10 @@
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"vm2": {
"version": "3.9.5",
"resolved": "https://registry.npmmirror.com/vm2/download/vm2-3.9.5.tgz",
"integrity": "sha1-UogESGC0u6zkQxAfzTvdsqCqJJY="
"solarlunar": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/solarlunar/-/solarlunar-2.0.7.tgz",
"integrity": "sha512-2SfuCCgAAxFU5MTMYuKGbRgRLcPTJQf3azMEw/GmBpHXA7N2eAQJStSqktZJjnq4qRCboBPnqEB866+PCregag=="
}
}
}

8
src/package.json Normal file
View File

@ -0,0 +1,8 @@
{
"dependencies": {
"axios": "^0.24.0",
"iconv-lite": "^0.6.3",
"pinyin-match": "^1.2.2",
"solarlunar": "^2.0.7"
}
}