Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

vm2

Package Overview
Dependencies
Maintainers
3
Versions
65
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

vm2 - npm Package Compare versions

Comparing version 3.9.11 to 3.9.12

lib/filesystem.js

5

CHANGELOG.md

@@ -0,1 +1,6 @@

v3.9.12 (2022-11-29)
--------------------
[new] Add file system API.
[fix] Fix parsing error with object patter in catch clause.
v3.9.11 (2022-08-28)

@@ -2,0 +7,0 @@ --------------------

import {EventEmitter} from 'events';
import fs from 'fs';
import pa from 'path';
/**
* Interface for nodes fs module
*/
export interface VMFS {
/** Implements fs.statSync */
statSync: typeof fs.statSync;
/** Implements fs.readFileSync */
readFileSync: typeof fs.readFileSync;
}
/**
* Interface for nodes path module
*/
export interface VMPath {
/** Implements path.resolve */
resolve: typeof pa.resolve;
/** Implements path.isAbsolute */
isAbsolute: typeof pa.isAbsolute;
/** Implements path.join */
join: typeof pa.join;
/** Implements path.basename */
basename: typeof pa.basename;
/** Implements path.dirname */
dirname: typeof pa.dirname;
/** Implements fs.statSync */
statSync: typeof fs.statSync;
/** Implements fs.readFileSync */
readFileSync: typeof fs.readFileSync;
}
/**
* Custom file system which abstracts functions from node's fs and path modules.
*/
export interface VMFileSystemInterface implements VMFS, VMPath {
/** Implements (sep) => sep === path.sep */
isSeparator(char: string): boolean;
}
/**
* Implementation of a default file system.
*/
export class VMFileSystem implements VMFileSystemInterface {
constructor(options?: {fs?: VMFS, path?: VMPath});
}
/**
* Require options for a VM

@@ -29,2 +76,4 @@ */

strict?: boolean;
/** FileSystem to load files from */
fs?: VMFileSystemInterface;
}

@@ -31,0 +80,0 @@

4

lib/main.js

@@ -15,2 +15,5 @@ 'use strict';

} = require('./nodevm');
const {
VMFileSystem
} = require('./filesystem');

@@ -21,1 +24,2 @@ exports.VMError = VMError;

exports.VM = VM;
exports.VMFileSystem = VMFileSystem;

26

lib/resolver-compat.js

@@ -6,3 +6,2 @@ 'use strict';

const fs = require('fs');
const pa = require('path');
const nmod = require('module');

@@ -19,2 +18,3 @@ const {EventEmitter} = require('events');

const {VMError} = require('./bridge');
const {DefaultFileSystem} = require('./filesystem');

@@ -51,4 +51,4 @@ /**

constructor(builtinModules, checkPath, globalPaths, pathContext, customResolver, hostRequire, compiler, strict, externals, allowTransitive) {
super(builtinModules, checkPath, globalPaths, pathContext, customResolver, hostRequire, compiler, strict);
constructor(fileSystem, builtinModules, checkPath, globalPaths, pathContext, customResolver, hostRequire, compiler, strict, externals, allowTransitive) {
super(fileSystem, builtinModules, checkPath, globalPaths, pathContext, customResolver, hostRequire, compiler, strict);
this.externals = externals;

@@ -270,3 +270,5 @@ this.currMod = undefined;

const DENY_RESOLVER = new Resolver({__proto__: null}, [], id => {
const DEFAULT_FS = new DefaultFileSystem();
const DENY_RESOLVER = new Resolver(DEFAULT_FS, {__proto__: null}, [], id => {
throw new VMError(`Access denied to require '${id}'`, 'EDENIED');

@@ -279,3 +281,3 @@ });

const builtins = genBuiltinsFromOptions(vm, undefined, undefined, override);
return new Resolver(builtins, [], defaultRequire);
return new Resolver(DEFAULT_FS, builtins, [], defaultRequire);
}

@@ -292,2 +294,3 @@

strict = true,
fs: fsOpt = DEFAULT_FS,
} = options;

@@ -297,7 +300,7 @@

if (!externalOpt) return new Resolver(builtins, [], hostRequire);
if (!externalOpt) return new Resolver(fsOpt, builtins, [], hostRequire);
let checkPath;
if (rootPaths) {
const checkedRootPaths = (Array.isArray(rootPaths) ? rootPaths : [rootPaths]).map(f => pa.resolve(f));
const checkedRootPaths = (Array.isArray(rootPaths) ? rootPaths : [rootPaths]).map(f => fsOpt.resolve(f));
checkPath = (filename) => {

@@ -307,5 +310,4 @@ return checkedRootPaths.some(path => {

const len = path.length;
if (filename.length === len || (len > 0 && path[len-1] === pa.sep)) return true;
const sep = filename[len];
return sep === '/' || sep === pa.sep;
if (filename.length === len || (len > 0 && fsOpt.isSeparator(path[len-1]))) return true;
return fsOpt.isSeparator(filename[len]);
});

@@ -337,3 +339,3 @@ };

if (typeof externalOpt !== 'object') {
return new DefaultResolver(builtins, checkPath, [], () => context, newCustomResolver, hostRequire, compiler, strict);
return new DefaultResolver(fsOpt, builtins, checkPath, [], () => context, newCustomResolver, hostRequire, compiler, strict);
}

@@ -349,5 +351,5 @@

externals = external.map(makeExternalMatcher);
return new LegacyResolver(builtins, checkPath, [], () => context, newCustomResolver, hostRequire, compiler, strict, externals, transitive);
return new LegacyResolver(fsOpt, builtins, checkPath, [], () => context, newCustomResolver, hostRequire, compiler, strict, externals, transitive);
}
exports.resolverFromOptions = resolverFromOptions;

@@ -5,5 +5,2 @@ 'use strict';

const pa = require('path');
const fs = require('fs');
const {

@@ -28,3 +25,4 @@ VMError

constructor(builtinModules, globalPaths, hostRequire) {
constructor(fs, builtinModules, globalPaths, hostRequire) {
this.fs = fs;
this.builtinModules = builtinModules;

@@ -40,3 +38,3 @@ this.globalPaths = globalPaths;

pathResolve(path) {
return pa.resolve(path);
return this.fs.resolve(path);
}

@@ -49,19 +47,19 @@

if (path.length <= idx) return false;
return path[idx] === '/' || path[idx] === pa.sep;
return this.fs.isSeparator(path[idx]);
}
pathIsAbsolute(path) {
return pa.isAbsolute(path);
return path !== '' && (this.fs.isSeparator(path[0]) || this.fs.isAbsolute(path));
}
pathConcat(...paths) {
return pa.join(...paths);
return this.fs.join(...paths);
}
pathBasename(path) {
return pa.basename(path);
return this.fs.basename(path);
}
pathDirname(path) {
return pa.dirname(path);
return this.fs.dirname(path);
}

@@ -147,4 +145,4 @@

constructor(builtinModules, checkPath, globalPaths, pathContext, customResolver, hostRequire, compiler, strict) {
super(builtinModules, globalPaths, hostRequire);
constructor(fs, builtinModules, checkPath, globalPaths, pathContext, customResolver, hostRequire, compiler, strict) {
super(fs, builtinModules, globalPaths, hostRequire);
this.checkPath = checkPath;

@@ -165,3 +163,3 @@ this.pathContext = pathContext;

try {
const stat = fs.statSync(path, {__proto__: null, throwIfNoEntry: false});
const stat = this.fs.statSync(path, {__proto__: null, throwIfNoEntry: false});
return stat && stat.isDirectory();

@@ -175,3 +173,3 @@ } catch (e) {

try {
const stat = fs.statSync(path, {__proto__: null, throwIfNoEntry: false});
const stat = this.fs.statSync(path, {__proto__: null, throwIfNoEntry: false});
return stat && stat.isFile();

@@ -184,3 +182,3 @@ } catch (e) {

readFile(path) {
return fs.readFileSync(path, {encoding: 'utf8'});
return this.fs.readFileSync(path, {encoding: 'utf8'});
}

@@ -187,0 +185,0 @@

@@ -110,3 +110,3 @@ /* global host, data, VMError */

const path = resolver.pathDirname(filename);
const path = resolver.fs.dirname(filename);
const module = new Module(filename, path, mod);

@@ -150,3 +150,3 @@ resolver.registerModule(module, filename, path, mod, direct);

function findBestExtensionHandler(filename) {
const name = resolver.pathBasename(filename);
const name = resolver.fs.basename(filename);
for (let i = 0; (i = localStringPrototypeIndexOf(name, '.', i + 1)) !== -1;) {

@@ -153,0 +153,0 @@ const ext = localStringPrototypeSlice(name, i);

@@ -106,2 +106,3 @@

let internStateValiable = undefined;
let tmpname = 'VM2_INTERNAL_TMPNAME';

@@ -116,11 +117,26 @@ acornWalkFull(ast, (node, state, type) => {

if (param) {
const name = assertType(param, 'Identifier').name;
const cBody = assertType(node.body, 'BlockStatement');
if (cBody.body.length > 0) {
if (param.type === 'ObjectPattern') {
insertions.push({
__proto__: null,
pos: cBody.body[0].start,
pos: node.start,
order: TO_RIGHT,
code: `catch($tmpname){try{throw ${INTERNAL_STATE_NAME}.handleException($tmpname);}`
});
insertions.push({
__proto__: null,
pos: node.body.end,
order: TO_LEFT,
code: `${name}=${INTERNAL_STATE_NAME}.handleException(${name});`
code: `}`
});
} else {
const name = assertType(param, 'Identifier').name;
const cBody = assertType(node.body, 'BlockStatement');
if (cBody.body.length > 0) {
insertions.push({
__proto__: null,
pos: cBody.body[0].start,
order: TO_LEFT,
code: `${name}=${INTERNAL_STATE_NAME}.handleException(${name});`
});
}
}

@@ -146,2 +162,4 @@ }

}
} else if (node.name.startsWith(tmpname)) {
tmpname = node.name + '_UNIQUE';
}

@@ -174,3 +192,3 @@ } else if (nodeType === 'ImportExpression') {

const change = insertions[i];
ncode += code.substring(curr, change.pos) + change.code;
ncode += code.substring(curr, change.pos) + change.code.replace(/\$tmpname/g, tmpname);
curr = change.pos;

@@ -177,0 +195,0 @@ }

@@ -16,3 +16,3 @@ {

],
"version": "3.9.11",
"version": "3.9.12",
"main": "index.js",

@@ -19,0 +19,0 @@ "sideEffects": false,

@@ -149,2 +149,3 @@ # vm2 [![NPM Version][npm-image]][npm-url] [![NPM Downloads][downloads-image]][downloads-url] [![Package Quality][quality-image]][quality-url] [![Node.js CI](https://github.com/patriksimek/vm2/actions/workflows/node-test.yml/badge.svg)](https://github.com/patriksimek/vm2/actions/workflows/node-test.yml) [![Known Vulnerabilities][snyk-image]][snyk-url]

* `require.strict` - `false` to not force strict mode on modules loaded by require (default: `true`).
* `require.fs` - Custom file system implementation.
* `nesting` - **WARNING**: Allowing this is a security risk as scripts can create a NodeVM which can require any host module. `true` to enable VMs nesting (default: `false`).

@@ -382,6 +383,7 @@ * `wrapper` - `commonjs` (default) to wrap script into CommonJS wrapper, `none` to retrieve value returned by the script.

* It is not possible to define a class that extends a proxied class.
* It is not possible to define a class that extends a proxied class. This includes using a proxied class in `Object.create`.
* Direct eval does not work.
* Logging sandbox arrays will repeat the array part in the properties.
* Source code transformations can result a different source string for a function.
* There are ways to crash the node process from inside the sandbox.

@@ -388,0 +390,0 @@ ## Deployment

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc