From 4a90b210c4df925bc4b3a2ce17f7bb80ec0bb98b Mon Sep 17 00:00:00 2001 From: rwaldron Date: Fri, 9 Feb 2024 12:02:01 -0500 Subject: [PATCH] fix: do not remap crypto if remapTypedArrays is false --- .../near-membrane-dom/src/browser-realm.ts | 9 +++++---- packages/near-membrane-dom/src/window.ts | 18 +++++++++++++++--- test/membrane/binary-data.spec.js | 12 ++++++++++++ 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/packages/near-membrane-dom/src/browser-realm.ts b/packages/near-membrane-dom/src/browser-realm.ts index ec9169dd..b8488ef8 100644 --- a/packages/near-membrane-dom/src/browser-realm.ts +++ b/packages/near-membrane-dom/src/browser-realm.ts @@ -80,7 +80,7 @@ function createIframeVirtualEnvironment( instrumentation, keepAlive = true, liveTargetCallback, - remapTypedArrays, + remapTypedArrays = true, signSourceCallback, // eslint-disable-next-line prefer-object-spread } = ObjectAssign({ __proto__: null }, providedOptions) as BrowserEnvironmentOptions; @@ -94,7 +94,8 @@ function createIframeVirtualEnvironment( typeof globalObjectShape !== 'object' || globalObjectShape === null; if (shouldUseDefaultGlobalOwnKeys && defaultGlobalOwnKeys === null) { defaultGlobalOwnKeys = filterWindowKeys( - getFilteredGlobalOwnKeys(redWindow, remapTypedArrays) + getFilteredGlobalOwnKeys(redWindow, remapTypedArrays), + remapTypedArrays ); } let blueConnector = blueCreateHooksCallbackCache.get(blueRefs.document) as @@ -145,7 +146,7 @@ function createIframeVirtualEnvironment( blueRefs.window, shouldUseDefaultGlobalOwnKeys ? (defaultGlobalOwnKeys as PropertyKey[]) - : filterWindowKeys(getFilteredGlobalOwnKeys(globalObjectShape)), + : filterWindowKeys(getFilteredGlobalOwnKeys(globalObjectShape), remapTypedArrays), // Chromium based browsers have a bug that nulls the result of `window` // getters in detached iframes when the property descriptor of `window.window` // is retrieved. @@ -159,7 +160,7 @@ function createIframeVirtualEnvironment( endowments, remapTypedArrays ); - removeWindowDescriptors(filteredEndowments); + removeWindowDescriptors(filteredEndowments, remapTypedArrays); env.remapProperties(blueRefs.window, filteredEndowments); } // We intentionally skip remapping Window.prototype because there is nothing diff --git a/packages/near-membrane-dom/src/window.ts b/packages/near-membrane-dom/src/window.ts index d8e6c071..923ad2b9 100644 --- a/packages/near-membrane-dom/src/window.ts +++ b/packages/near-membrane-dom/src/window.ts @@ -62,7 +62,7 @@ export function getCachedGlobalObjectReferences( return record; } -export function filterWindowKeys(keys: PropertyKey[]): PropertyKey[] { +export function filterWindowKeys(keys: PropertyKey[], remapTypedArrays: boolean): PropertyKey[] { const result: PropertyKey[] = []; let resultOffset = 0; for (let i = 0, { length } = keys; i < length; i += 1) { @@ -74,7 +74,11 @@ export function filterWindowKeys(keys: PropertyKey[]): PropertyKey[] { key !== 'top' && key !== 'window' && // Remove other browser specific unforgeables. - key !== 'chrome' + key !== 'chrome' && + // Crypto and typed arrays must be from the same global object + !remapTypedArrays && + key !== 'Crypto' && + key !== 'crypto' ) { result[resultOffset++] = key; } @@ -109,7 +113,10 @@ export function filterWindowKeys(keys: PropertyKey[]): PropertyKey[] { * that will be installed (via the membrane) as global descriptors in * the red realm. */ -export function removeWindowDescriptors(unsafeDescs: T): T { +export function removeWindowDescriptors( + unsafeDescs: T, + remapTypedArrays: boolean +): T { // Remove unforgeable descriptors that cannot be installed. ReflectDeleteProperty(unsafeDescs, 'document'); ReflectDeleteProperty(unsafeDescs, 'location'); @@ -117,6 +124,11 @@ export function removeWindowDescriptors(unsafeD ReflectDeleteProperty(unsafeDescs, 'window'); // Remove other browser specific unforgeables. ReflectDeleteProperty(unsafeDescs, 'chrome'); + // Crypto and typed arrays must be from the same global object + if (!remapTypedArrays) { + ReflectDeleteProperty(unsafeDescs, 'crypto'); + ReflectDeleteProperty(unsafeDescs, 'Crypto'); + } return unsafeDescs; } diff --git a/test/membrane/binary-data.spec.js b/test/membrane/binary-data.spec.js index 9c6a639d..e0869e6f 100644 --- a/test/membrane/binary-data.spec.js +++ b/test/membrane/binary-data.spec.js @@ -48,6 +48,18 @@ describe('Crypto', () => { endowments: Object.getOwnPropertyDescriptors({ expect }), }); + env.evaluate(` + expect(() => { + crypto.getRandomValues(new Uint8Array(1)); + }).not.toThrow(); + `); + }); + it('works when typed arrays are remapped', () => { + const env = createVirtualEnvironment(window, { + endowments: Object.getOwnPropertyDescriptors({ expect }), + remapTypedArrays: false, + }); + env.evaluate(` expect(() => { crypto.getRandomValues(new Uint8Array(1));