A sandbox boundary violation in vm2 allows host object identity to cross into the sandbox through host Promise resolution.
When a host-side Promise that resolves to a host object is exposed to the sandbox, the value delivered to the sandbox .then() callback preserves host identity. This allows the sandbox to interact with the host object directly, including:
WeakMapThis behavior occurs because the Promise fulfillment wrapper uses ensureThis() instead of the stronger cross-realm conversion path (from() / proxy wrapping). If no prototype mapping is found, ensureThis() returns the original object.
As a result, objects resolved by host Promises can cross the sandbox boundary without proper isolation.
In setup-sandbox.js, vm2 wraps Promise.prototype.then:
globalPromise.prototype.then = function then(onFulfilled, onRejected) {
resetPromiseSpecies(this);
if (typeof onFulfilled === 'function') {
const origOnFulfilled = onFulfilled;
onFulfilled = function onFulfilled(value) {
value = ensureThis(value);
return apply(origOnFulfilled, this, [value]);
};
}
return apply(globalPromiseThen, this, [onFulfilled, onRejected]);
};
The wrapper calls ensureThis(value) before invoking the sandbox callback.
However, ensureThis is implemented in bridge.js as thisEnsureThis():
function thisEnsureThis(other) {
const type = typeof other;
switch (type) {
case 'object':
if (other === null) return null;
case 'function':
let proto = thisReflectGetPrototypeOf(other);
if (!proto) {
return other;
}
while (proto) {
const mapping = thisReflectApply(thisMapGet, protoMappings, [proto]);
if (mapping) {
const mapped = thisReflectApply(thisWeakMapGet, mappingOtherToThis, [other]);
if (mapped) return mapped;...
3.11.0Exploitability
AV:NAC:LPR:NUI:NScope
S:UImpact
C:LI:LA:N6.5/CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N