+252
-71
@@ -43,2 +43,3 @@ 'use strict'; | ||
| 'URIError', | ||
| 'SuppressedError', | ||
| 'Error' | ||
@@ -67,2 +68,49 @@ ]; | ||
| // Add non-global function constructor prototypes for cross-realm blocking. | ||
| // These are not on `global` but are needed to block sandbox escape via | ||
| // AsyncFunction('code'), GeneratorFunction('code'), etc. | ||
| try { | ||
| thisGlobalPrototypes['AsyncFunction'] = (async function() {}).constructor.prototype; | ||
| } catch (e) {} | ||
| try { | ||
| thisGlobalPrototypes['GeneratorFunction'] = (function*() {}).constructor.prototype; | ||
| } catch (e) {} | ||
| try { | ||
| // Use eval to avoid syntax error on Node < 10 where async generators don't exist | ||
| thisGlobalPrototypes['AsyncGeneratorFunction'] = eval('(async function*() {})').constructor.prototype; | ||
| } catch (e) {} | ||
| // Cache this-realm dangerous function constructors. | ||
| // Used to block raw host Function constructors from leaking when handler | ||
| // methods are called directly (e.g., via showProxy handler exposure). | ||
| // This complements isDangerousFunctionConstructor which checks OTHER-realm constructors. | ||
| let thisAsyncFunctionCtor; | ||
| let thisGeneratorFunctionCtor; | ||
| let thisAsyncGeneratorFunctionCtor; | ||
| try { | ||
| if (thisGlobalPrototypes.AsyncFunction) { | ||
| const desc = thisReflectGetOwnPropertyDescriptor(thisGlobalPrototypes.AsyncFunction, 'constructor'); | ||
| if (desc) thisAsyncFunctionCtor = desc.value; | ||
| } | ||
| } catch (e) {} | ||
| try { | ||
| if (thisGlobalPrototypes.GeneratorFunction) { | ||
| const desc = thisReflectGetOwnPropertyDescriptor(thisGlobalPrototypes.GeneratorFunction, 'constructor'); | ||
| if (desc) thisGeneratorFunctionCtor = desc.value; | ||
| } | ||
| } catch (e) {} | ||
| try { | ||
| if (thisGlobalPrototypes.AsyncGeneratorFunction) { | ||
| const desc = thisReflectGetOwnPropertyDescriptor(thisGlobalPrototypes.AsyncGeneratorFunction, 'constructor'); | ||
| if (desc) thisAsyncGeneratorFunctionCtor = desc.value; | ||
| } | ||
| } catch (e) {} | ||
| function isThisDangerousFunctionConstructor(value) { | ||
| return value === thisFunction || | ||
| (thisAsyncFunctionCtor && value === thisAsyncFunctionCtor) || | ||
| (thisGeneratorFunctionCtor && value === thisGeneratorFunctionCtor) || | ||
| (thisAsyncGeneratorFunctionCtor && value === thisAsyncGeneratorFunctionCtor); | ||
| } | ||
| const { | ||
@@ -240,2 +288,6 @@ getPrototypeOf: thisReflectGetPrototypeOf, | ||
| const handlerToObject = new ThisWeakMap(); | ||
| // Store factory functions in a WeakMap keyed by handler instance. | ||
| // This prevents exposure of factory functions via util.inspect with showProxy:true, | ||
| // which would allow attackers to create new handlers wrapping attacker-controlled objects. | ||
| const handlerToFactory = new ThisWeakMap(); | ||
@@ -249,2 +301,9 @@ // Closure-scoped function to retrieve the wrapped object from a handler. | ||
| // Closure-scoped function to retrieve the factory from a handler. | ||
| // This is NOT a method on BaseHandler, so it cannot be called by attackers | ||
| // even if they obtain a reference to the handler via showProxy. | ||
| function getHandlerFactory(handler) { | ||
| return thisReflectApply(thisWeakMapGet, handlerToFactory, [handler]); | ||
| } | ||
| // Closure-scoped function to convert other-realm objects to this-realm with factory. | ||
@@ -254,5 +313,60 @@ // This is NOT a method on BaseHandler, so it cannot be called by attackers | ||
| function handlerFromOtherWithContext(handler, other) { | ||
| return thisFromOtherWithFactory(handler.getFactory(), other); | ||
| return thisFromOtherWithFactory(getHandlerFactory(handler), other); | ||
| } | ||
| // Closure-scoped function to prevent extensions on a proxy target. | ||
| // This is NOT a method on BaseHandler, so it cannot be called by attackers | ||
| // even if they obtain a reference to the handler via showProxy. | ||
| // Unlike other handler methods which use getHandlerObject(this), the old | ||
| // doPreventExtensions accepted `object` as a direct parameter, allowing | ||
| // attackers to pass crafted objects. Now it retrieves `object` from the WeakMap. | ||
| function doPreventExtensions(handler, target) { | ||
| // Note: handler@this(unsafe) target@this(unsafe) throws@this(unsafe) | ||
| const object = getHandlerObject(handler); // @other(unsafe) | ||
| let keys; // @other(safe-array-of-prim) | ||
| try { | ||
| keys = otherReflectOwnKeys(object); | ||
| } catch (e) { // @other(unsafe) | ||
| throw thisFromOtherForThrow(e); | ||
| } | ||
| for (let i = 0; i < keys.length; i++) { | ||
| const key = keys[i]; // @prim | ||
| // Skip dangerous cross-realm symbols | ||
| if (isDangerousCrossRealmSymbol(key)) continue; | ||
| let desc; | ||
| try { | ||
| desc = otherSafeGetOwnPropertyDescriptor(object, key); | ||
| } catch (e) { // @other(unsafe) | ||
| throw thisFromOtherForThrow(e); | ||
| } | ||
| if (!desc) continue; | ||
| if (!desc.configurable) { | ||
| const current = thisSafeGetOwnPropertyDescriptor(target, key); | ||
| if (current && !current.configurable) continue; | ||
| if (desc.get || desc.set) { | ||
| desc.get = handlerFromOtherWithContext(handler, desc.get); | ||
| desc.set = handlerFromOtherWithContext(handler, desc.set); | ||
| } else if (typeof object === 'function' && (key === 'caller' || key === 'callee' || key === 'arguments')) { | ||
| desc.value = null; | ||
| } else { | ||
| desc.value = handlerFromOtherWithContext(handler, desc.value); | ||
| } | ||
| } else { | ||
| if (desc.get || desc.set) { | ||
| desc = { | ||
| __proto__: null, | ||
| configurable: true, | ||
| enumerable: desc.enumerable, | ||
| writable: true, | ||
| value: null | ||
| }; | ||
| } else { | ||
| desc.value = null; | ||
| } | ||
| } | ||
| if (!thisReflectDefineProperty(target, key, desc)) throw thisUnexpected(); | ||
| } | ||
| if (!thisReflectPreventExtensions(target)) throw thisUnexpected(); | ||
| } | ||
| function thisAddProtoMapping(proto, other, name) { | ||
@@ -262,3 +376,3 @@ // Note: proto@this(unsafe) other@other(unsafe) name@this(unsafe) throws@this(unsafe) | ||
| thisReflectApply(thisMapSet, protoMappings, [other, | ||
| (factory, object) => thisProxyOther(factory, object, proto)]); | ||
| (factory, object, preventUnwrap) => thisProxyOther(factory, object, proto, preventUnwrap)]); | ||
| if (name) thisReflectApply(thisMapSet, protoName, [proto, name]); | ||
@@ -271,3 +385,3 @@ } | ||
| thisReflectApply(thisMapSet, protoMappings, [other, | ||
| (factory, object) => { | ||
| (factory, object, preventUnwrap) => { | ||
| if (!proto) { | ||
@@ -278,3 +392,3 @@ proto = protoFactory(); | ||
| } | ||
| return thisProxyOther(factory, object, proto); | ||
| return thisProxyOther(factory, object, proto, preventUnwrap); | ||
| }]); | ||
@@ -345,2 +459,84 @@ } | ||
| // Cache the other realm's Function constructors to block them from crossing the bridge. | ||
| // This prevents sandbox escape via indirect access paths like | ||
| // Object.getOwnPropertyDescriptor(Function.prototype, 'constructor').value | ||
| // We block all code-executing constructors: Function, AsyncFunction, GeneratorFunction, AsyncGeneratorFunction | ||
| // IMPORTANT: We must get these from otherGlobalPrototypes (the OTHER realm), not from | ||
| // local function instances which would give us THIS realm's constructors. | ||
| let otherFunctionCtor; | ||
| let otherAsyncFunctionCtor; | ||
| let otherGeneratorFunctionCtor; | ||
| let otherAsyncGeneratorFunctionCtor; | ||
| try { | ||
| const desc = otherSafeGetOwnPropertyDescriptor(otherGlobalPrototypes.Function, 'constructor'); | ||
| if (desc) otherFunctionCtor = desc.value; | ||
| } catch (e) { | ||
| // If we can't get it, the get trap's constructor case still provides protection | ||
| } | ||
| // Get AsyncFunction, GeneratorFunction, AsyncGeneratorFunction constructors from OTHER realm | ||
| try { | ||
| if (otherGlobalPrototypes.AsyncFunction) { | ||
| const desc = otherSafeGetOwnPropertyDescriptor(otherGlobalPrototypes.AsyncFunction, 'constructor'); | ||
| if (desc) otherAsyncFunctionCtor = desc.value; | ||
| } | ||
| } catch (e) {} | ||
| try { | ||
| if (otherGlobalPrototypes.GeneratorFunction) { | ||
| const desc = otherSafeGetOwnPropertyDescriptor(otherGlobalPrototypes.GeneratorFunction, 'constructor'); | ||
| if (desc) otherGeneratorFunctionCtor = desc.value; | ||
| } | ||
| } catch (e) {} | ||
| try { | ||
| if (otherGlobalPrototypes.AsyncGeneratorFunction) { | ||
| const desc = otherSafeGetOwnPropertyDescriptor(otherGlobalPrototypes.AsyncGeneratorFunction, 'constructor'); | ||
| if (desc) otherAsyncGeneratorFunctionCtor = desc.value; | ||
| } | ||
| } catch (e) {} | ||
| function isDangerousFunctionConstructor(value) { | ||
| return value === otherFunctionCtor || | ||
| value === otherAsyncFunctionCtor || | ||
| value === otherGeneratorFunctionCtor || | ||
| (otherAsyncGeneratorFunctionCtor && value === otherAsyncGeneratorFunctionCtor); // AsyncGeneratorFunction is not available on Node < 10 | ||
| } | ||
| // Check if an object contains a dangerous function constructor in ANY of its | ||
| // own property values (data or accessor), recursively at any nesting depth. | ||
| // Uses cycle detection and otherSafeGetOwnPropertyDescriptor (not otherReflectGet) | ||
| // to avoid triggering getters. | ||
| function containsDangerousConstructor(obj, visited) { | ||
| if (obj === null || typeof obj !== 'object') return false; | ||
| if (!visited) visited = new ThisWeakMap(); | ||
| if (thisReflectApply(thisWeakMapGet, visited, [obj])) return false; | ||
| thisReflectApply(thisWeakMapSet, visited, [obj, true]); | ||
| let keys; | ||
| try { | ||
| keys = otherReflectOwnKeys(obj); | ||
| } catch (e) { | ||
| return false; | ||
| } | ||
| for (let i = 0; i < keys.length; i++) { | ||
| let desc; | ||
| try { | ||
| desc = otherSafeGetOwnPropertyDescriptor(obj, keys[i]); | ||
| } catch (e) { | ||
| continue; | ||
| } | ||
| if (!desc) continue; | ||
| if (desc.get || desc.set) { | ||
| if (isDangerousFunctionConstructor(desc.get) || isDangerousFunctionConstructor(desc.set)) return true; | ||
| } else { | ||
| if (isDangerousFunctionConstructor(desc.value)) return true; | ||
| if (desc.value !== null && typeof desc.value === 'object') { | ||
| if (containsDangerousConstructor(desc.value, visited)) return true; | ||
| } | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
| function thisOtherHasOwnProperty(object, key) { | ||
@@ -395,56 +591,10 @@ // Note: object@other(safe) key@prim throws@this(unsafe) | ||
| thisReflectApply(thisWeakMapSet, handlerToObject, [this, object]); | ||
| // Store the factory in a WeakMap instead of as a method. | ||
| // NOTE: There is intentionally NO getFactory() method on this class. | ||
| // The factory is retrieved via the closure-scoped getHandlerFactory() function, | ||
| // which is not accessible to attackers even if they obtain a handler reference. | ||
| // Subclass constructors override this with their specific factory. | ||
| thisReflectApply(thisWeakMapSet, handlerToFactory, [this, defaultFactory]); | ||
| } | ||
| getFactory() { | ||
| return defaultFactory; | ||
| } | ||
| doPreventExtensions(target, object, factory) { | ||
| // Note: target@this(unsafe) object@other(unsafe) throws@this(unsafe) | ||
| let keys; // @other(safe-array-of-prim) | ||
| try { | ||
| keys = otherReflectOwnKeys(object); | ||
| } catch (e) { // @other(unsafe) | ||
| throw thisFromOtherForThrow(e); | ||
| } | ||
| for (let i = 0; i < keys.length; i++) { | ||
| const key = keys[i]; // @prim | ||
| // Skip dangerous cross-realm symbols | ||
| if (isDangerousCrossRealmSymbol(key)) continue; | ||
| let desc; | ||
| try { | ||
| desc = otherSafeGetOwnPropertyDescriptor(object, key); | ||
| } catch (e) { // @other(unsafe) | ||
| throw thisFromOtherForThrow(e); | ||
| } | ||
| if (!desc) continue; | ||
| if (!desc.configurable) { | ||
| const current = thisSafeGetOwnPropertyDescriptor(target, key); | ||
| if (current && !current.configurable) continue; | ||
| if (desc.get || desc.set) { | ||
| desc.get = handlerFromOtherWithContext(this,desc.get); | ||
| desc.set = handlerFromOtherWithContext(this,desc.set); | ||
| } else if (typeof object === 'function' && (key === 'caller' || key === 'callee' || key === 'arguments')) { | ||
| desc.value = null; | ||
| } else { | ||
| desc.value = handlerFromOtherWithContext(this,desc.value); | ||
| } | ||
| } else { | ||
| if (desc.get || desc.set) { | ||
| desc = { | ||
| __proto__: null, | ||
| configurable: true, | ||
| enumerable: desc.enumerable, | ||
| writable: true, | ||
| value: null | ||
| }; | ||
| } else { | ||
| desc.value = null; | ||
| } | ||
| } | ||
| if (!thisReflectDefineProperty(target, key, desc)) throw thisUnexpected(); | ||
| } | ||
| if (!thisReflectPreventExtensions(target)) throw thisUnexpected(); | ||
| } | ||
| get(target, key, receiver) { | ||
@@ -458,7 +608,15 @@ if (key === 'isProxy') return true; | ||
| if (desc) { | ||
| if (desc.value && desc.value.name === 'Function') return {}; | ||
| if (desc.value && isDangerousFunctionConstructor(desc.value)) return {}; | ||
| return thisDefaultGet(this, object, key, desc); | ||
| } | ||
| const proto = thisReflectGetPrototypeOf(target); | ||
| return proto === null ? undefined : proto.constructor; | ||
| if (proto === null) return undefined; | ||
| const ctor = proto.constructor; | ||
| // Defense in depth: block this-realm dangerous function constructors. | ||
| // Normally handler methods are only called by the proxy mechanism | ||
| // which handles return values safely, but if the handler is exposed | ||
| // (e.g., via util.inspect showProxy), attackers can call get() | ||
| // directly with a forged target, leaking raw host constructors. | ||
| if (isThisDangerousFunctionConstructor(ctor)) return {}; | ||
| return ctor; | ||
| } | ||
@@ -542,3 +700,3 @@ case '__proto__': { | ||
| } | ||
| return thisFromOtherWithFactory(this.getFactory(), ret, thisFromOther(object)); | ||
| return thisFromOtherWithFactory(getHandlerFactory(this), ret, thisFromOther(object)); | ||
| } | ||
@@ -550,2 +708,8 @@ | ||
| if (desc && typeof object === 'function' && (prop === 'arguments' || prop === 'caller' || prop === 'callee')) desc.value = null; | ||
| // Block sandbox access to host's Function constructor via getOwnPropertyDescriptor. | ||
| // This mirrors the protection in the get() trap at the 'constructor' case. | ||
| // Only block when sandbox (!isHost) accesses host objects, not when host inspects sandbox. | ||
| if (!isHost && desc && prop === 'constructor' && desc.value && isDangerousFunctionConstructor(desc.value)) { | ||
| return undefined; | ||
| } | ||
| return desc; | ||
@@ -686,3 +850,3 @@ } | ||
| if (thisReflectIsExtensible(target)) { | ||
| this.doPreventExtensions(target, object, this); | ||
| doPreventExtensions(this, target); | ||
| } | ||
@@ -728,3 +892,3 @@ return false; | ||
| if (thisReflectIsExtensible(target)) { | ||
| this.doPreventExtensions(target, object, this); | ||
| doPreventExtensions(this, target); | ||
| } | ||
@@ -759,4 +923,5 @@ return true; | ||
| getFactory() { | ||
| return protectedFactory; | ||
| constructor(object) { | ||
| super(object); | ||
| thisReflectApply(thisWeakMapSet, handlerToFactory, [this, protectedFactory]); | ||
| } | ||
@@ -793,4 +958,5 @@ | ||
| getFactory() { | ||
| return readonlyFactory; | ||
| constructor(object) { | ||
| super(object); | ||
| thisReflectApply(thisWeakMapSet, handlerToFactory, [this, readonlyFactory]); | ||
| } | ||
@@ -867,3 +1033,3 @@ | ||
| function thisProxyOther(factory, other, proto) { | ||
| function thisProxyOther(factory, other, proto, preventUnwrap) { | ||
| const target = thisCreateTargetObject(other, proto); | ||
@@ -873,3 +1039,5 @@ const handler = factory(other); | ||
| try { | ||
| otherReflectApply(otherWeakMapSet, mappingThisToOther, [proxy, other]); | ||
| if (!preventUnwrap) { | ||
| otherReflectApply(otherWeakMapSet, mappingThisToOther, [proxy, other]); | ||
| } | ||
| registerProxy(proxy, handler); | ||
@@ -988,6 +1156,19 @@ } catch (e) { | ||
| case 'function': | ||
| // Block the other realm's Function constructors from crossing the bridge. | ||
| if (!isHost && isDangerousFunctionConstructor(other)) { | ||
| return emptyFrozenObject; | ||
| } | ||
| // Cache check first — if already proxied, return existing proxy. | ||
| // Safe because: cached proxies were created under the same preventUnwrap | ||
| // rules, and an attacker can't retroactively add Function constructors | ||
| // to a host object's properties from the sandbox (chicken-and-egg). | ||
| const mapped = thisReflectApply(thisWeakMapGet, mappingOtherToThis, [other]); | ||
| if (mapped) return mapped; | ||
| // For objects on sandbox side, check for nested dangerous constructors. | ||
| // If found, proxy WITHOUT unwrap registration (mappingThisToOther), so | ||
| // the proxy cannot be unwrapped when passed back to host functions. | ||
| // The proxy's get trap already sanitizes dangerous values on read. | ||
| const dangerous = !isHost && containsDangerousConstructor(other); | ||
| if (proto) { | ||
| return thisProxyOther(factory, other, proto); | ||
| return thisProxyOther(factory, other, proto, dangerous); | ||
| } | ||
@@ -1000,7 +1181,7 @@ try { | ||
| if (!proto) { | ||
| return thisProxyOther(factory, other, null); | ||
| return thisProxyOther(factory, other, null, dangerous); | ||
| } | ||
| do { | ||
| const mapping = thisReflectApply(thisMapGet, protoMappings, [proto]); | ||
| if (mapping) return mapping(factory, other); | ||
| if (mapping) return mapping(factory, other, dangerous); | ||
| try { | ||
@@ -1012,3 +1193,3 @@ proto = otherReflectGetPrototypeOf(proto); | ||
| } while (proto); | ||
| return thisProxyOther(factory, other, thisObjectPrototype); | ||
| return thisProxyOther(factory, other, thisObjectPrototype, dangerous); | ||
| case 'undefined': | ||
@@ -1015,0 +1196,0 @@ case 'string': |
+68
-10
@@ -208,3 +208,3 @@ /* global host, bridge, data, context */ | ||
| onRejected = function onRejected(error) { | ||
| error = ensureThis(error); | ||
| error = handleException(error); | ||
| return apply(origOnRejected, this, [error]); | ||
@@ -221,3 +221,3 @@ }; | ||
| onRejected = function onRejected(error) { | ||
| error = ensureThis(error); | ||
| error = handleException(error); | ||
| return apply(origOnRejected, this, [error]); | ||
@@ -279,2 +279,22 @@ }; | ||
| /* | ||
| * WebAssembly.JSTag protection | ||
| * | ||
| * WebAssembly.JSTag (Node 25+) allows wasm exception handling to catch JavaScript | ||
| * exceptions via try_table/catch with JSTag. This completely bypasses the transformer's | ||
| * catch block instrumentation, which only wraps JavaScript catch clauses with | ||
| * handleException(). An attacker can: | ||
| * 1. Create a wasm module that imports JSTag and catches JS exceptions | ||
| * 2. Import a function that triggers a host TypeError (e.g., via Symbol() name trick) | ||
| * 3. Catch the host error in wasm, returning it as an externref | ||
| * 4. Use the raw host error's constructor chain to escape | ||
| * | ||
| * Fix: Remove WebAssembly.JSTag from the sandbox. Without it, wasm code cannot | ||
| * catch JavaScript exceptions — catch_all provides no value access, and catch_all_ref | ||
| * requires JSTag for exn.extract. The tag is a V8 internal and cannot be reconstructed. | ||
| */ | ||
| if (typeof WebAssembly !== 'undefined' && WebAssembly.JSTag !== undefined) { | ||
| localReflectDeleteProperty(WebAssembly, 'JSTag'); | ||
| } | ||
| if (!localReflectDefineProperty(global, 'VMError', { | ||
@@ -527,2 +547,45 @@ __proto__: null, | ||
| /* | ||
| * SuppressedError sanitization | ||
| * | ||
| * When V8 internally creates SuppressedError during DisposableStack.dispose() | ||
| * or 'using' declarations, the .error and .suppressed properties may contain | ||
| * host-realm errors (e.g., TypeError from Symbol() name trick). Since the | ||
| * SuppressedError is created in the sandbox context, ensureThis returns it | ||
| * as-is, leaving its sub-error properties unsanitized. | ||
| * | ||
| * Fix: handleException detects SuppressedError instances and recursively | ||
| * sanitizes their .error and .suppressed properties via ensureThis. | ||
| */ | ||
| const localSuppressedErrorProto = (typeof SuppressedError === 'function') ? SuppressedError.prototype : null; | ||
| function handleException(e, visited) { | ||
| e = ensureThis(e); | ||
| if (localSuppressedErrorProto !== null && e !== null && typeof e === 'object') { | ||
| if (!visited) visited = new LocalWeakMap(); | ||
| // Cycle detection: if we've already visited this object, stop recursing | ||
| if (apply(localWeakMapGet, visited, [e])) return e; | ||
| apply(localWeakMapSet, visited, [e, true]); | ||
| let proto; | ||
| try { | ||
| proto = localReflectGetPrototypeOf(e); | ||
| } catch (ex) { | ||
| return e; | ||
| } | ||
| while (proto !== null) { | ||
| if (proto === localSuppressedErrorProto) { | ||
| e.error = handleException(e.error, visited); | ||
| e.suppressed = handleException(e.suppressed, visited); | ||
| return e; | ||
| } | ||
| try { | ||
| proto = localReflectGetPrototypeOf(proto); | ||
| } catch (ex) { | ||
| return e; | ||
| } | ||
| } | ||
| } | ||
| return e; | ||
| } | ||
| const withProxy = localObjectFreeze({ | ||
@@ -542,3 +605,3 @@ __proto__: null, | ||
| }, | ||
| handleException: ensureThis, | ||
| handleException, | ||
| import(what) { | ||
@@ -738,3 +801,3 @@ throw new VMError('Dynamic Import not supported'); | ||
| args[1] = function sanitizedOnRejected(error) { | ||
| error = ensureThis(error); | ||
| error = handleException(error); | ||
| return localReflectApply(onRejected, this, [error]); | ||
@@ -755,3 +818,3 @@ }; | ||
| args[0] = function sanitizedOnRejected(error) { | ||
| error = ensureThis(error); | ||
| error = handleException(error); | ||
| return localReflectApply(onRejected, this, [error]); | ||
@@ -839,7 +902,2 @@ }; | ||
| localObject.defineProperty(localObject, 'setPrototypeOf', { | ||
| value: () => { | ||
| throw new VMError('Operation not allowed on contextified object.'); | ||
| } | ||
| }); | ||
@@ -846,0 +904,0 @@ function readonly(other, mock) { |
+2
-2
@@ -16,3 +16,3 @@ { | ||
| ], | ||
| "version": "3.10.4", | ||
| "version": "3.10.5", | ||
| "main": "index.js", | ||
@@ -23,3 +23,3 @@ "sideEffects": false, | ||
| "dependencies": { | ||
| "acorn": "^8.14.1", | ||
| "acorn": "^8.15.0", | ||
| "acorn-walk": "^8.3.4" | ||
@@ -26,0 +26,0 @@ }, |
+2
-2
@@ -143,3 +143,3 @@ # vm2 [![NPM Version][npm-image]][npm-url] [![NPM Downloads][downloads-image]][downloads-url] [![License][license-image]][license-url] [](https://github.com/patriksimek/vm2/actions/workflows/test.yml) [![Known Vulnerabilities][snyk-image]][snyk-url] | ||
| - `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`). | ||
| - `wasm` - If set to `false` any attempt to compile a WebAssembly module will throw a `WebAssembly.CompileError` (default: `true`). Note: `WebAssembly.JSTag` is removed inside the sandbox for security reasons, so wasm code cannot catch JavaScript exceptions. | ||
| - `allowAsync` - If set to `false` any attempt to run code using `async` will throw a `VMError` (default: `true`). | ||
@@ -179,3 +179,3 @@ | ||
| - `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`). | ||
| - `wasm` - If set to `false` any attempt to compile a WebAssembly module will throw a `WebAssembly.CompileError` (default: `true`). Note: `WebAssembly.JSTag` is removed inside the sandbox for security reasons, so wasm code cannot catch JavaScript exceptions. | ||
| - `sourceExtensions` - Array of file extensions to treat as source code (default: `['js']`). | ||
@@ -182,0 +182,0 @@ - `require` - `true`, an object or a Resolver to enable `require` method (default: `false`). |
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
244060
4.87%6377
3.67%1
Infinity%Updated