Skip to content

Commit e128936

Browse files
authored
fix(utils): Support crypto.getRandomValues in old Chromium versions (#9251)
Here is my proposal to fix `getRandomByte` function throwing an error due to `crypto.getRandomValues` returning `undefined` in old browser engines like Chromium 23. This error could be fixed as well by using a polyfill in every project that imports and uses Sentry but, since the change of this PR only involved keeping the `Uint8Array` reference in a variable, I thought it would be worth it to give it a try.
1 parent 72c3488 commit e128936

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

packages/utils/src/misc.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,15 @@ export function uuid4(): string {
3131
return crypto.randomUUID().replace(/-/g, '');
3232
}
3333
if (crypto && crypto.getRandomValues) {
34-
getRandomByte = () => crypto.getRandomValues(new Uint8Array(1))[0];
34+
getRandomByte = () => {
35+
// crypto.getRandomValues might return undefined instead of the typed array
36+
// in old Chromium versions (e.g. 23.0.1235.0 (151422))
37+
// However, `typedArray` is still filled in-place.
38+
// @see https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues#typedarray
39+
const typedArray = new Uint8Array(1);
40+
crypto.getRandomValues(typedArray);
41+
return typedArray[0];
42+
};
3543
}
3644
} catch (_) {
3745
// some runtimes can crash invoking crypto

packages/utils/test/misc.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,25 @@ describe('uuid4 generation', () => {
343343
expect(uuid4()).toMatch(uuid4Regex);
344344
}
345345
});
346+
347+
// Corner case related to crypto.getRandomValues being only
348+
// semi-implemented (e.g. Chromium 23.0.1235.0 (151422))
349+
it('returns valid uuid v4 even if crypto.getRandomValues does not return a typed array', () => {
350+
// eslint-disable-next-line @typescript-eslint/no-var-requires
351+
const cryptoMod = require('crypto');
352+
353+
const getRandomValues = (typedArray: Uint8Array) => {
354+
if (cryptoMod.getRandomValues) {
355+
cryptoMod.getRandomValues(typedArray);
356+
}
357+
};
358+
359+
(global as any).crypto = { getRandomValues };
360+
361+
for (let index = 0; index < 1_000; index++) {
362+
expect(uuid4()).toMatch(uuid4Regex);
363+
}
364+
});
346365
});
347366

348367
describe('arrayify()', () => {

0 commit comments

Comments
 (0)