Allow privileged Compartments before lockdown
This is a preliminary change to decouple Compartment and lockdown.
MODIFY
packages/ses/src/make-eval-function.js
packages/ses/src/make-eval-function.js
-import { assert } from './assertions.js';
-import { defineProperties, getConstructorOf } from './commons.js';
+import { defineProperties } from './commons.js';
import { performEval } from './evaluate.js';
/**
@@ -32,14 +31,5 @@ export const makeEvalFunction = (realmRec, globalObject, options = {}) => {
},
});
- assert(
- getConstructorOf(newEval) !== Function,
- 'eval constructor is Function',
- );
- assert(
- getConstructorOf(newEval) !== realmRec.intrinsics.Function,
- 'eval contructions is %Function%',
- );
-
return newEval;
};

MODIFY
packages/ses/src/make-function-constructor.js
packages/ses/src/make-function-constructor.js
@@ -3,7 +3,6 @@ import {
arrayJoin,
arrayPop,
defineProperties,
- getConstructorOf,
getPrototypeOf,
} from './commons.js';
import { performEval } from './evaluate.js';
@@ -60,12 +59,14 @@ export function makeFunctionConstructor(realmRec, globaObject, options = {}) {
});
// Assert identity of Function.__proto__ accross all compartments
- assert(getPrototypeOf(Function) === Function.prototype);
- assert(getPrototypeOf(newFunction) === Function.prototype);
-
- // Assert that the unsafe Function is not leaking
- assert(getConstructorOf(newFunction) !== Function);
- assert(getConstructorOf(newFunction) !== realmRec.intrinsics.Function);
+ assert(
+ getPrototypeOf(Function) === Function.prototype,
+ 'Function prototype is the same accross compartments',
+ );
+ assert(
+ getPrototypeOf(newFunction) === Function.prototype,
+ 'Function constructor prototype is the same accross compartments',
+ );
return newFunction;
}

MODIFY
packages/ses/test/lockdown.test.js
packages/ses/test/lockdown.test.js
import test from 'tape';
+import Compartment from '../src/compartment-shim.js';
import { lockdown } from '../src/lockdown-shim.js';
test('lockdown returns boolean or throws in SES', t => {
- t.plan(6);
+ // Compartment constructor does not throw before lockdown.
+ (() => {
+ const c = new Compartment({}, {}, {});
+ const functionConstructor = c.evaluate('Function.prototype.constructor');
+ t.equal(
+ functionConstructor,
+ Function,
+ 'before lockdown, compartments have the same privileged Function.prototype.constructor as the start compartment',
+ );
+ })();
t.ok(lockdown(), 'return true when called from JS without options');
t.notOk(
@@ -25,4 +35,25 @@ test('lockdown returns boolean or throws in SES', t => {
() => lockdown({ noTameRegExp: true }),
'throws when attempting to untame RegExp',
);
+
+ // Compartment constructor does not throw after lockdown.
+ (() => {
+ const c = new Compartment({}, {}, {});
+ const cf = c.evaluate('Function.prototype.constructor');
+ t.notEqual(
+ cf,
+ Function,
+ 'after lockdown, Function.prototype.constructor must be tamed inside compartments',
+ );
+
+ const d = new Compartment({}, {}, {});
+ const df = d.evaluate('Function.prototype.constructor');
+ t.equal(
+ cf,
+ df,
+ 'after lockdown, every compartment must have the same tamed Function.prototype.constructor',
+ );
+ })();
+
+ t.end();
});

Allow privileged Compartments before lockdown (#260)

This is a preliminary change to decouple Compartment and lockdown. #259