Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dosya #518

Closed
wants to merge 12 commits into from
3 changes: 2 additions & 1 deletion .eslintignore
@@ -1,3 +1,4 @@
/test.js
/node-*
/lib/events.js
/lib/events.js
/test/additional-modules/my-es-module/index.js
14 changes: 11 additions & 3 deletions CHANGELOG.md
@@ -1,11 +1,19 @@
v3.9.3 (2022-12-08)
v3.9.15 (2023-04-06)
--------------------
[fix] Security fix (see https://github.com/patriksimek/vm2/issues/515).

v3.9.14 (2023-02-05)
--------------------
[new] Support conditional export resolution with custom resolver. (nick-klaviyo)

v3.9.13 (2022-12-08)
--------------------
[fix] Fix typescript errors in index.d.ts

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

v3.9.11 (2022-08-28)
--------------------
Expand Down Expand Up @@ -179,7 +187,7 @@ v3.5.1 (2017-10-04)

v3.5.0 (2017-08-31)
-------------------
[new] Allow a custom compiler to recieve the filetype (Orta Therox)
[new] Allow a custom compiler to receive 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)
Expand Down
2 changes: 1 addition & 1 deletion index.d.ts
Expand Up @@ -82,7 +82,7 @@ export interface VMRequire {
/** Collection of mock modules (both external or built-in). */
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 | undefined;
resolve?: (moduleName: string, parentDirname: string) => string | { path: string, module?: string } | undefined;
/** Custom require to require host and built-in modules. */
customRequire?: (id: string) => any;
/** Load modules in strict mode. (default: true) */
Expand Down
9 changes: 7 additions & 2 deletions lib/resolver-compat.js
Expand Up @@ -322,8 +322,13 @@ function resolverFromOptions(vm, options, override, compiler) {
}
const resolved = customResolver(x, path);
if (!resolved) return undefined;
if (externals) externals.push(new RegExp('^' + escapeRegExp(resolved)));
return resolver.loadAsFileOrDirecotry(resolved, extList);
if (typeof resolved === 'string') {
if (externals) externals.push(new RegExp('^' + escapeRegExp(resolved)));
return resolver.loadAsFileOrDirectory(resolved, extList);
}
const {module=x, path: resolvedPath} = resolved;
if (externals) externals.push(new RegExp('^' + escapeRegExp(resolvedPath)));
return resolver.loadNodeModules(module, [resolvedPath], extList);
};
}

Expand Down
12 changes: 6 additions & 6 deletions lib/resolver.js
Expand Up @@ -242,7 +242,7 @@ class DefaultResolver extends Resolver {
// 2. If X begins with '/'
if (this.pathIsAbsolute(x)) {
// a. set Y to be the filesystem root
f = this.loadAsFileOrDirecotry(x, extList);
f = this.loadAsFileOrDirectory(x, extList);
if (f) return f;

// c. THROW "not found"
Expand All @@ -256,21 +256,21 @@ class DefaultResolver extends Resolver {
for (let i = 0; i < paths.length; i++) {
// a. LOAD_AS_FILE(Y + X)
// b. LOAD_AS_DIRECTORY(Y + X)
f = this.loadAsFileOrDirecotry(this.pathConcat(paths[i], x), extList);
f = this.loadAsFileOrDirectory(this.pathConcat(paths[i], x), extList);
if (f) return f;
}
} else if (paths === undefined) {
// a. LOAD_AS_FILE(Y + X)
// b. LOAD_AS_DIRECTORY(Y + X)
f = this.loadAsFileOrDirecotry(this.pathConcat(path, x), extList);
f = this.loadAsFileOrDirectory(this.pathConcat(path, x), extList);
if (f) return f;
} else {
throw new VMError('Invalid options.paths option.');
}
} else {
// a. LOAD_AS_FILE(Y + X)
// b. LOAD_AS_DIRECTORY(Y + X)
f = this.loadAsFileOrDirecotry(this.pathConcat(path, x), extList);
f = this.loadAsFileOrDirectory(this.pathConcat(path, x), extList);
if (f) return f;
}

Expand Down Expand Up @@ -315,7 +315,7 @@ class DefaultResolver extends Resolver {
return super.resolveFull(mod, x, options, ext, direct);
}

loadAsFileOrDirecotry(x, extList) {
loadAsFileOrDirectory(x, extList) {
// a. LOAD_AS_FILE(X)
const f = this.loadAsFile(x, extList);
if (f) return f;
Expand Down Expand Up @@ -555,7 +555,7 @@ class DefaultResolver extends Resolver {
} else {
// a. LOAD_AS_FILE(RESOLVED_PATH)
// b. LOAD_AS_DIRECTORY(RESOLVED_PATH)
f = this.loadAsFileOrDirecotry(resolvedPath, extList);
f = this.loadAsFileOrDirectory(resolvedPath, extList);
}
if (f) return f;
// 5. THROW "not found"
Expand Down
25 changes: 21 additions & 4 deletions lib/setup-sandbox.js
Expand Up @@ -276,13 +276,30 @@ if (typeof OriginalCallSite === 'function') {
return;
}
const newWrapped = (error, sst) => {
const sandboxSst = ensureThis(sst);
if (localArrayIsArray(sst)) {
for (let i=0; i < sst.length; i++) {
const cs = sst[i];
if (typeof cs === 'object' && localReflectGetPrototypeOf(cs) === OriginalCallSite.prototype) {
sst[i] = new CallSite(cs);
if (sst === sandboxSst) {
for (let i=0; i < sst.length; i++) {
const cs = sst[i];
if (typeof cs === 'object' && localReflectGetPrototypeOf(cs) === OriginalCallSite.prototype) {
sst[i] = new CallSite(cs);
}
}
} else {
sst = [];
for (let i=0; i < sandboxSst.length; i++) {
const cs = sandboxSst[i];
localReflectDefineProperty(sst, i, {
__proto__: null,
value: new CallSite(cs),
enumerable: true,
configurable: true,
writable: true
});
}
}
} else {
sst = sandboxSst;
}
return value(error, sst);
};
Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -13,7 +13,7 @@
"alcatraz",
"contextify"
],
"version": "3.9.13",
"version": "3.9.15",
"main": "index.js",
"sideEffects": false,
"repository": "github:patriksimek/vm2",
Expand Down
1 change: 1 addition & 0 deletions test/additional-modules/my-es-module/index.cjs
@@ -0,0 +1 @@
module.exports = {additional_cjs_module: true};
1 change: 1 addition & 0 deletions test/additional-modules/my-es-module/index.js
@@ -0,0 +1 @@
export default {additional_es_module: true};
12 changes: 12 additions & 0 deletions test/additional-modules/my-es-module/package.json
@@ -0,0 +1,12 @@
{
"main": "index.js",
"type": "module",
"exports": {
".": {
"default": {
"require": "./index.cjs",
"default": "./index.js"
}
}
}
}
11 changes: 11 additions & 0 deletions test/nodevm.js
Expand Up @@ -239,6 +239,17 @@ describe('modules', () => {
assert.ok(vm.run("require('my-module')", __filename));
});

it('can resolve conditional exports with a custom resolver', () => {
const vm = new NodeVM({
require: {
external: ['my-es-module'],
resolve: () => ({ path: path.resolve(__dirname, 'additional-modules') })
}
});

assert.ok(vm.run("require('my-es-module')", __filename));
});

it('allows for multiple root folders', () => {
const vm = new NodeVM({
require: {
Expand Down