From a689ae7216baab3ee9362daa96c3ef0efbdad549 Mon Sep 17 00:00:00 2001 From: Daniel Griesser Date: Thu, 7 Sep 2023 11:08:09 +0200 Subject: [PATCH 1/2] fix: uuidv4 fix for cloudflare --- packages/utils/src/misc.ts | 16 +++++++++++----- packages/utils/test/misc.test.ts | 30 +++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/packages/utils/src/misc.ts b/packages/utils/src/misc.ts index a474c8e157e4..e7ceb905de5a 100644 --- a/packages/utils/src/misc.ts +++ b/packages/utils/src/misc.ts @@ -25,13 +25,19 @@ export function uuid4(): string { const gbl = GLOBAL_OBJ as typeof GLOBAL_OBJ & CryptoGlobal; const crypto = gbl.crypto || gbl.msCrypto; - if (crypto && crypto.randomUUID) { - return crypto.randomUUID().replace(/-/g, ''); + let getRandomByte = (): number => Math.random() * 16; + try { + if (crypto) { + if (crypto.randomUUID) { + return crypto.randomUUID().replace(/-/g, ''); + } + getRandomByte = () => crypto.getRandomValues && crypto.getRandomValues(new Uint8Array(1))[0]; + } + } catch (_) { + // some runtimes can crash invoking crypto + // https://github.com/getsentry/sentry-javascript/issues/8935 } - const getRandomByte = - crypto && crypto.getRandomValues ? () => crypto.getRandomValues(new Uint8Array(1))[0] : () => Math.random() * 16; - // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523 // Concatenating the following numbers as strings results in '10000000100040008000100000000000' return (([1e7] as unknown as string) + 1e3 + 4e3 + 8e3 + 1e11).replace(/[018]/g, c => diff --git a/packages/utils/test/misc.test.ts b/packages/utils/test/misc.test.ts index aaac0d46c0b0..dc75b70d4286 100644 --- a/packages/utils/test/misc.test.ts +++ b/packages/utils/test/misc.test.ts @@ -290,11 +290,12 @@ describe('checkOrSetAlreadyCaught()', () => { }); describe('uuid4 generation', () => { + const uuid4Regex = /^[0-9A-F]{12}[4][0-9A-F]{3}[89AB][0-9A-F]{15}$/i; // Jest messes with the global object, so there is no global crypto object in any node version // For this reason we need to create our own crypto object for each test to cover all the code paths it('returns valid uuid v4 ids via Math.random', () => { for (let index = 0; index < 1_000; index++) { - expect(uuid4()).toMatch(/^[0-9A-F]{12}[4][0-9A-F]{3}[89AB][0-9A-F]{15}$/i); + expect(uuid4()).toMatch(uuid4Regex); } }); @@ -305,7 +306,7 @@ describe('uuid4 generation', () => { (global as any).crypto = { getRandomValues: cryptoMod.getRandomValues }; for (let index = 0; index < 1_000; index++) { - expect(uuid4()).toMatch(/^[0-9A-F]{12}[4][0-9A-F]{3}[89AB][0-9A-F]{15}$/i); + expect(uuid4()).toMatch(uuid4Regex); } }); @@ -316,7 +317,30 @@ describe('uuid4 generation', () => { (global as any).crypto = { randomUUID: cryptoMod.randomUUID }; for (let index = 0; index < 1_000; index++) { - expect(uuid4()).toMatch(/^[0-9A-F]{12}[4][0-9A-F]{3}[89AB][0-9A-F]{15}$/i); + expect(uuid4()).toMatch(uuid4Regex); + } + }); + + it("return valid uuid v4 even if crypto doesn't exists", () => { + (global as any).crypto = { getRandomValues: undefined, randomUUID: undefined }; + + for (let index = 0; index < 1_000; index++) { + expect(uuid4()).toMatch(uuid4Regex); + } + }); + + it('return valid uuid v4 even if crypto invoked causes an error', () => { + (global as any).crypto = { + getRandomValues: () => { + throw new Error('yo'); + }, + randomUUID: () => { + throw new Error('yo'); + }, + }; + + for (let index = 0; index < 1_000; index++) { + expect(uuid4()).toMatch(uuid4Regex); } }); }); From bf0ac450c446c259127646cd4e25f301ead87eeb Mon Sep 17 00:00:00 2001 From: Daniel Griesser Date: Thu, 7 Sep 2023 11:26:23 +0200 Subject: [PATCH 2/2] ref: Style --- packages/utils/src/misc.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/utils/src/misc.ts b/packages/utils/src/misc.ts index e7ceb905de5a..9799df421c31 100644 --- a/packages/utils/src/misc.ts +++ b/packages/utils/src/misc.ts @@ -27,11 +27,11 @@ export function uuid4(): string { let getRandomByte = (): number => Math.random() * 16; try { - if (crypto) { - if (crypto.randomUUID) { - return crypto.randomUUID().replace(/-/g, ''); - } - getRandomByte = () => crypto.getRandomValues && crypto.getRandomValues(new Uint8Array(1))[0]; + if (crypto && crypto.randomUUID) { + return crypto.randomUUID().replace(/-/g, ''); + } + if (crypto && crypto.getRandomValues) { + getRandomByte = () => crypto.getRandomValues(new Uint8Array(1))[0]; } } catch (_) { // some runtimes can crash invoking crypto