Skip to content

Commit

Permalink
Harden endowments
Browse files Browse the repository at this point in the history
Update AVA config

Add harden for default endowments and test

Add some refactoring and fix coverage issues

Add endowment registry

Add hardening for special endowment cases (snap & ethereum)

Refactor nyc config

Revert hardening of the ethereum endowment

Update ava test runner config

Revert default-endowments.ts
  • Loading branch information
david0xd committed Dec 20, 2022
1 parent ddffcf5 commit 3c1ed7a
Show file tree
Hide file tree
Showing 63 changed files with 1,577 additions and 38 deletions.
2 changes: 1 addition & 1 deletion packages/snaps-execution-environments/.c8rc.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"reporter": ["html", "json-summary", "text", "json"],
"reporter": ["html", "json-summary", "json"],
"exclude": ["*.js", "./src/index.ts", "**/*.ava.test.ts"],
"report-dir": "./coverage-ava"
}
2 changes: 1 addition & 1 deletion packages/snaps-execution-environments/ava.config.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
module.exports = () => {
return {
concurrency: 5,
extensions: ['ts'],
require: ['ts-node/register'],
verbose: true,
files: ['src/**/*.ava.test.ts'],
timeout: '30s',
};
};
12 changes: 4 additions & 8 deletions packages/snaps-execution-environments/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,16 @@ const deepmerge = require('deepmerge');

const baseConfig = require('../../jest.config.base');

delete baseConfig.coverageThreshold;

module.exports = deepmerge(baseConfig, {
coveragePathIgnorePatterns: ['./src/index.ts', '.ava.test.ts'],
coverageThreshold: {
global: {
branches: 83.93,
functions: 92.25,
lines: 87.07,
statements: 87.18,
},
},
testEnvironment: '<rootDir>/jest.environment.js',
testEnvironmentOptions: {
customExportConditions: ['node', 'node-addons'],
},
testTimeout: 2500,
testPathIgnorePatterns: ['.ava.test.ts'],
coverageProvider: 'v8',
coverageReporters: ['html', 'json-summary', 'json'],
});
1 change: 1 addition & 0 deletions packages/snaps-execution-environments/jest.environment.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ module.exports = class CustomTestEnvironment extends TestEnvironment {
this.global.TextDecoder = TextDecoder;
this.global.ArrayBuffer = ArrayBuffer;
this.global.Uint8Array = Uint8Array;
this.global.harden = (param) => param;
}
}
};
10 changes: 10 additions & 0 deletions packages/snaps-execution-environments/nyc.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* NYC coverage reporter configuration.
*/
module.exports = {
'check-coverage': true,
branches: 83.68,
lines: 87.11,
functions: 92.19,
statements: 87.22,
};
4 changes: 2 additions & 2 deletions packages/snaps-execution-environments/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
"dist/"
],
"scripts": {
"test": "yarn test:ava && jest && yarn posttest && yarn merge:coverage",
"test": "yarn test:ava && jest && yarn merge:coverage",
"posttest": "jest-it-up --margin 0.25",
"test:ava": "c8 ava",
"merge:coverage": "yarn mkdirp coverage-all && shx cp coverage/coverage-final.json coverage-all/coverage-final-jest.json && shx cp coverage-ava/coverage-final.json coverage-all/coverage-final-ava.json && rimraf 'coverage' 'coverage-ava' && nyc merge coverage-all coverage-merged/merged-coverage.json && nyc report -t coverage-merged --report-dir coverage --reporter=html --reporter=json-summary --reporter=json && rimraf 'coverage-merged' 'coverage-all'",
"merge:coverage": "yarn mkdirp coverage-all && shx cp coverage/coverage-final.json coverage-all/coverage-final-jest.json && shx cp coverage-ava/coverage-final.json coverage-all/coverage-final-ava.json && rimraf 'coverage' 'coverage-ava' && nyc merge coverage-all coverage-merged/merged-coverage.json && nyc report -t coverage-merged --report-dir coverage --reporter=text --reporter=html --reporter=json-summary --reporter=json && rimraf 'coverage-merged' 'coverage-all'",
"test:ci": "yarn test",
"test:watch": "jest --watch",
"lint:eslint": "eslint . --cache --ext js,ts",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// eslint-disable-next-line import/no-unassigned-import
import 'ses';
import test from 'ava';

import abortControllerEndowment from './abortController';

test.before(() => {
lockdown({
domainTaming: 'unsafe',
errorTaming: 'unsafe',
stackFiltering: 'verbose',
});
});

test('modifying AbortController endowment properties should result with throwing an error', (expect) => {
const { AbortController: _AbortController } =
abortControllerEndowment.factory();

expect.throws(
() => {
// @ts-expect-error Ignore because error is caused intentionally
_AbortController.whatever = 'something';
},
{
message: `Cannot add property whatever, object is not extensible`,
},
);
});

test('modifying AbortController endowment prototype should result with throwing an error', (expect) => {
const { AbortController: _AbortController } =
abortControllerEndowment.factory();

expect.throws(() => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error Ignore because this 'mistake' is intentional
_AbortController.prototype = { poisoned: 'prototype' };
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Creates AbortController function hardened by SES.
*
* @returns An object with the attenuated `AbortController` function.
*/
const createAbortController = () => {
return {
AbortController: harden(AbortController),
} as const;
};

const endowmentModule = {
names: ['AbortController'] as const,
factory: createAbortController,
};
export default endowmentModule;
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// eslint-disable-next-line import/no-unassigned-import
import 'ses';
import test from 'ava';

import abortSignalEndowment from './abortSignal';

test.before(() => {
lockdown({
domainTaming: 'unsafe',
errorTaming: 'unsafe',
stackFiltering: 'verbose',
});
});

test('modifying AbortSignal endowment properties should result with throwing an error', (expect) => {
const { AbortSignal: _AbortSignal } = abortSignalEndowment.factory();

expect.throws(
() => {
// @ts-expect-error Ignore because error is caused intentionally
_AbortSignal.whatever = 'something';
},
{
message: `Cannot add property whatever, object is not extensible`,
},
);
});

test('modifying AbortSignal endowment prototype should result with throwing an error', (expect) => {
const { AbortSignal: _AbortSignal } = abortSignalEndowment.factory();

expect.throws(() => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error Ignore because this 'mistake' is intentional
_AbortSignal.prototype = { poisoned: 'prototype' };
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Creates AbortSignal function hardened by SES.
*
* @returns An object with the attenuated `AbortSignal` function.
*/
const createAbortSignal = () => {
return {
AbortSignal: harden(AbortSignal),
} as const;
};

const endowmentModule = {
names: ['AbortSignal'] as const,
factory: createAbortSignal,
};
export default endowmentModule;
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// eslint-disable-next-line import/no-unassigned-import
import 'ses';
import test from 'ava';

import arrayBufferEndowment from './arrayBuffer';

test.before(() => {
lockdown({
domainTaming: 'unsafe',
errorTaming: 'unsafe',
stackFiltering: 'verbose',
});
});

test('modifying ArrayBuffer endowment properties should result with throwing an error', (expect) => {
const { ArrayBuffer: _ArrayBuffer } = arrayBufferEndowment.factory();

expect.throws(
() => {
// @ts-expect-error Ignore because error is caused intentionally
_ArrayBuffer.whatever = 'something';
},
{
message: `Cannot add property whatever, object is not extensible`,
},
);
});

test('modifying ArrayBuffer endowment prototype should result with throwing an error', (expect) => {
const { ArrayBuffer: _ArrayBuffer } = arrayBufferEndowment.factory();

expect.throws(() => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error Ignore because this 'mistake' is intentional
_ArrayBuffer.prototype = { poisoned: 'prototype' };
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Creates ArrayBuffer function hardened by SES.
*
* @returns An object with the attenuated `ArrayBuffer` function.
*/
const createArrayBuffer = () => {
return {
ArrayBuffer: harden(ArrayBuffer),
} as const;
};

const endowmentModule = {
names: ['ArrayBuffer'] as const,
factory: createArrayBuffer,
};
export default endowmentModule;
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// eslint-disable-next-line import/no-unassigned-import
import 'ses';
import test from 'ava';

import atobEndowment from './atob';

test.before(() => {
lockdown({
domainTaming: 'unsafe',
errorTaming: 'unsafe',
stackFiltering: 'verbose',
});
});

test('modifying atob should not be allowed and error should be thrown', (expect) => {
const { atob: _atob } = atobEndowment.factory();

expect.throws(
() => {
// @ts-expect-error Ignore because this is intentionally causing an error
_atob.whatever = 'something';
},
{
message: `Cannot add property whatever, object is not extensible`,
},
);
});

test('atob should work properly after hardening', (expect) => {
const { atob: _atob } = atobEndowment.factory();
const decoded = _atob('U25hcHM=');

expect.is(decoded, 'Snaps');
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Creates atob function hardened by SES.
*
* @returns An object with the attenuated `atob` function.
*/
const createAtob = () => {
const _atob = (data: string) => {
return atob(harden(data));
};

return {
atob: harden(_atob),
} as const;
};

const endowmentModule = {
names: ['atob'] as const,
factory: createAtob,
};
export default endowmentModule;
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// eslint-disable-next-line import/no-unassigned-import
import 'ses';
import test from 'ava';

import bigIntEndowment from './bigInt';

test.before(() => {
lockdown({
domainTaming: 'unsafe',
errorTaming: 'unsafe',
stackFiltering: 'verbose',
});
});

test('modifying BigInt should not be allowed and error should be thrown', (expect) => {
const { BigInt: _BigInt } = bigIntEndowment.factory();

expect.throws(
() => {
// @ts-expect-error Ignore because this is intentionally causing an error
_BigInt.whatever = 'something';
},
{
message: `Cannot add property whatever, object is not extensible`,
},
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Creates BigInt function hardened by SES.
*
* @returns An object with the attenuated `BigInt` function.
*/
const createBigInt = () => {
return {
BigInt: harden(BigInt),
} as const;
};

const endowmentModule = {
names: ['BigInt'] as const,
factory: createBigInt,
};
export default endowmentModule;
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// eslint-disable-next-line import/no-unassigned-import
import 'ses';
import test from 'ava';

import bigInt64ArrayEndowment from './bigInt64Array';

test.before(() => {
lockdown({
domainTaming: 'unsafe',
errorTaming: 'unsafe',
stackFiltering: 'verbose',
});
});

test('modifying BigInt64Array endowment properties should result with throwing an error', (expect) => {
const { BigInt64Array: _BigInt64Array } = bigInt64ArrayEndowment.factory();

expect.throws(
() => {
// @ts-expect-error Ignore because error is caused intentionally
_BigInt64Array.whatever = 'something';
},
{
message: `Cannot add property whatever, object is not extensible`,
},
);
});

test('modifying BigInt64Array endowment prototype should result with throwing an error', (expect) => {
const { BigInt64Array: _BigInt64Array } = bigInt64ArrayEndowment.factory();

expect.throws(() => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error Ignore because this 'mistake' is intentional
_BigInt64Array.prototype = { poisoned: 'prototype' };
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Creates BigInt64Array function hardened by SES.
*
* @returns An object with the attenuated `BigInt64Array` function.
*/
const createBigInt64Array = () => {
return {
BigInt64Array: harden(BigInt64Array),
} as const;
};

const endowmentModule = {
names: ['BigInt64Array'] as const,
factory: createBigInt64Array,
};
export default endowmentModule;
Loading

0 comments on commit 3c1ed7a

Please sign in to comment.