Skip to content

Commit 825bdc6

Browse files
committed
fix(ses)!: align with XS property censorship agreement
1 parent 39d9031 commit 825bdc6

7 files changed

+119
-49
lines changed

packages/ses/src/permits.js

+9-4
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ function TypedArrayPrototype(constructor) {
326326
}
327327

328328
// Without Math.random
329-
const SharedMath = {
329+
const CommonMath = {
330330
E: 'number',
331331
LN10: 'number',
332332
LN2: 'number',
@@ -649,12 +649,16 @@ export const permitted = {
649649
},
650650

651651
'%InitialMath%': {
652-
...SharedMath,
653-
// random is standard but omitted from SharedMath
652+
...CommonMath,
653+
// `%InitialMath%.random()` has the standard unsafe behavior
654654
random: fn,
655655
},
656656

657-
'%SharedMath%': SharedMath,
657+
'%SharedMath%': {
658+
...CommonMath,
659+
// `%SharedMath%.random()` is tamed to always throw
660+
random: fn,
661+
},
658662

659663
'%InitialDate%': {
660664
// Properties of the Date Constructor
@@ -668,6 +672,7 @@ export const permitted = {
668672
'%SharedDate%': {
669673
// Properties of the Date Constructor
670674
'[[Proto]]': '%FunctionPrototype%',
675+
// `%SharedDate%.now()` is tamed to always throw
671676
now: fn,
672677
parse: fn,
673678
prototype: '%DatePrototype%',

packages/ses/src/tame-date-constructor.js

+37-21
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,38 @@ export default function tameDateConstructor(dateTaming = 'safe') {
1717

1818
// Use concise methods to obtain named functions without constructors.
1919
const tamedMethods = {
20+
/**
21+
* `%SharedDate%.now()` throw a `TypeError` starting with "secure mode".
22+
* See https://github.com/endojs/endo/issues/910#issuecomment-1581855420
23+
*/
2024
now() {
21-
return NaN;
25+
throw TypeError('secure mode Calling %SharedDate%.now() throws');
2226
},
2327
};
2428

25-
// Tame the Date constructor.
26-
// Common behavior
27-
// * new Date(x) coerces x into a number and then returns a Date
28-
// for that number of millis since the epoch
29-
// * new Date(NaN) returns a Date object which stringifies to
30-
// 'Invalid Date'
31-
// * new Date(undefined) returns a Date object which stringifies to
32-
// 'Invalid Date'
33-
// OriginalDate (normal standard) behavior
34-
// * Date(anything) gives a string with the current time
35-
// * new Date() returns the current time, as a Date object
36-
// SharedDate behavior
37-
// * Date(anything) returned 'Invalid Date'
38-
// * new Date() returns a Date object which stringifies to
39-
// 'Invalid Date'
29+
/**
30+
* Tame the Date constructor.
31+
* See https://github.com/endojs/endo/issues/910#issuecomment-1581855420
32+
*
33+
* Common behavior
34+
* * `new Date(x)` coerces x into a number and then returns a Date
35+
* for that number of millis since the epoch
36+
* * `new Date(NaN)` returns a Date object which stringifies to
37+
* 'Invalid Date'
38+
* * `new Date(undefined)` returns a Date object which stringifies to
39+
* 'Invalid Date'
40+
*
41+
* OriginalDate (normal standard) behavior preserved by
42+
* `%InitialDate%`.
43+
* * `Date(anything)` gives a string with the current time
44+
* * `new Date()` returns the current time, as a Date object
45+
*
46+
* `%SharedDate%` behavior
47+
* * `Date(anything)` throws a TypeError starting with "secure mode"
48+
* * `new Date()` throws a TypeError starting with "secure mode"
49+
*
50+
* @param {{powers?: string}} [opts]
51+
*/
4052
const makeDateConstructor = ({ powers = 'none' } = {}) => {
4153
let ResultDate;
4254
if (powers === 'original') {
@@ -51,10 +63,14 @@ export default function tameDateConstructor(dateTaming = 'safe') {
5163
// eslint-disable-next-line no-shadow
5264
ResultDate = function Date(...rest) {
5365
if (new.target === undefined) {
54-
return 'Invalid Date';
66+
throw TypeError(
67+
'secure mode Calling %SharedDate% constructor as a function throws',
68+
);
5569
}
5670
if (rest.length === 0) {
57-
rest = [NaN];
71+
throw TypeError(
72+
'secure mode Calling new %SharedDate%() with no arguments throws',
73+
);
5874
}
5975
return construct(OriginalDate, rest, new.target);
6076
};
@@ -69,13 +85,13 @@ export default function tameDateConstructor(dateTaming = 'safe') {
6985
configurable: false,
7086
},
7187
parse: {
72-
value: Date.parse,
88+
value: OriginalDate.parse,
7389
writable: true,
7490
enumerable: false,
7591
configurable: true,
7692
},
7793
UTC: {
78-
value: Date.UTC,
94+
value: OriginalDate.UTC,
7995
writable: true,
8096
enumerable: false,
8197
configurable: true,
@@ -88,7 +104,7 @@ export default function tameDateConstructor(dateTaming = 'safe') {
88104

89105
defineProperties(InitialDate, {
90106
now: {
91-
value: Date.now,
107+
value: OriginalDate.now,
92108
writable: true,
93109
enumerable: false,
94110
configurable: true,

packages/ses/src/tame-math-object.js

+20-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,26 @@ export default function tameMathObject(mathTaming = 'safe') {
1616
const { random: _, ...otherDescriptors } =
1717
getOwnPropertyDescriptors(originalMath);
1818

19-
const sharedMath = create(objectPrototype, otherDescriptors);
19+
// Use concise methods to obtain named functions without constructors.
20+
const tamedMethods = {
21+
/**
22+
* `%SharedMath%.random()` throws a TypeError starting with "secure mode".
23+
* See https://github.com/endojs/endo/issues/910#issuecomment-1581855420
24+
*/
25+
random() {
26+
throw TypeError('secure mode %SharedMath%.random() throws');
27+
},
28+
};
29+
30+
const sharedMath = create(objectPrototype, {
31+
...otherDescriptors,
32+
random: {
33+
value: tamedMethods.random,
34+
writable: true,
35+
enumerable: false,
36+
configurable: true,
37+
},
38+
});
2039

2140
return {
2241
'%InitialMath%': initialMath,

packages/ses/test/test-tame-date-unit.js

+22-10
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,34 @@ test('tameDateConstructor - initial constructor without argument', t => {
1010
const date = new InitialDate();
1111

1212
t.truthy(date instanceof InitialDate);
13+
t.truthy(date instanceof SharedDate);
1314
// eslint-disable-next-line no-proto
1415
t.is(date.__proto__.constructor, SharedDate);
16+
t.is(date.constructor, SharedDate);
1517

1618
t.not(date.toString(), 'Invalid Date');
1719
});
1820

1921
test('tameDateConstructor - shared constructor without argument', t => {
2022
t.is(SharedDate.name, 'Date');
2123

22-
const date = new SharedDate();
24+
t.throws(() => new SharedDate(), {
25+
message: /^secure mode/,
26+
});
27+
});
2328

24-
t.truthy(date instanceof SharedDate);
25-
// eslint-disable-next-line no-proto
26-
t.is(date.__proto__.constructor, SharedDate);
29+
test('tameDateConstructor - initial constructor called as function', t => {
30+
const date = InitialDate(undefined);
2731

28-
t.is(date.toString(), 'Invalid Date');
32+
t.not(date.toString(), 'Invalid Date');
2933
});
3034

31-
test('tameDateConstructor - shared constructor now', t => {
32-
t.is(SharedDate.now.name, 'now');
33-
34-
const date = SharedDate.now();
35+
test('tameDateConstructor - shared constructor called as function', t => {
36+
t.is(SharedDate.name, 'Date');
3537

36-
t.truthy(Number.isNaN(date));
38+
t.throws(() => SharedDate(undefined), {
39+
message: /^secure mode/,
40+
});
3741
});
3842

3943
test('tameDateConstructor - initial constructor now', t => {
@@ -43,3 +47,11 @@ test('tameDateConstructor - initial constructor now', t => {
4347

4448
t.truthy(Number(date) > 1);
4549
});
50+
51+
test('tameDateConstructor - shared constructor now', t => {
52+
t.is(SharedDate.now.name, 'now');
53+
54+
t.throws(() => SharedDate.now(), {
55+
message: /^secure mode/,
56+
});
57+
});

packages/ses/test/test-tame-date.js

+20-10
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,37 @@ test('lockdown start Date is powerful', t => {
1818
test('lockdown Date.prototype.constructor is powerless', t => {
1919
const SharedDate = Date.prototype.constructor;
2020
t.not(Date, SharedDate);
21-
t.truthy(Number.isNaN(SharedDate.now()));
22-
t.is(`${new SharedDate()}`, 'Invalid Date');
21+
22+
t.throws(() => SharedDate.now(), {
23+
message: /^secure mode/,
24+
});
25+
26+
t.throws(() => new SharedDate(), {
27+
message: /^secure mode/,
28+
});
2329
});
2430

2531
test('lockdown Date in Compartment is powerless', t => {
2632
const c = new Compartment();
2733
t.is(c.evaluate('Date.parse("1982-04-09")'), Date.parse('1982-04-09'));
2834

29-
const now = c.evaluate('Date.now()');
30-
t.truthy(Number.isNaN(now));
35+
t.throws(() => c.evaluate('Date.now()'), {
36+
message: /^secure mode/,
37+
});
3138

32-
const newDate = c.evaluate('new Date()');
33-
t.is(`${newDate}`, 'Invalid Date');
39+
t.throws(() => c.evaluate('new Date()'), {
40+
message: /^secure mode/,
41+
});
3442
});
3543

3644
test('lockdown Date in nested Compartment is powerless', t => {
3745
const c = new Compartment().evaluate('new Compartment()');
3846

39-
const now = c.evaluate('Date.now()');
40-
t.truthy(Number.isNaN(now));
47+
t.throws(() => c.evaluate('Date.now()'), {
48+
message: /^secure mode/,
49+
});
4150

42-
const newDate = c.evaluate('new Date()');
43-
t.is(`${newDate}`, 'Invalid Date');
51+
t.throws(() => c.evaluate('new Date()'), {
52+
message: /^secure mode/,
53+
});
4454
});

packages/ses/test/test-tame-math-unit.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,7 @@ test('tameMathObject - initial properties', t => {
1111
});
1212

1313
test('tameMathObject - shared properties', t => {
14-
t.is(typeof sharedMath.random, 'undefined');
14+
t.throws(() => sharedMath.random(), {
15+
message: /^secure mode/,
16+
});
1517
});

packages/ses/test/test-tame-math.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,16 @@ test('lockdown start Math is powerful', t => {
1212

1313
test('lockdown Math from Compartment is powerless', t => {
1414
const c = new Compartment();
15-
t.is(c.evaluate('typeof Math.random'), 'undefined');
15+
16+
t.throws(() => c.evaluate('Math.random()'), {
17+
message: /^secure mode/,
18+
});
1619
});
1720

1821
test('lockdown Math from nested Compartment is powerless', t => {
1922
const c = new Compartment().evaluate('new Compartment()');
20-
t.is(c.evaluate('typeof Math.random'), 'undefined');
23+
24+
t.throws(() => c.evaluate('Math.random()'), {
25+
message: /^secure mode/,
26+
});
2127
});

0 commit comments

Comments
 (0)