From 9a02edd9dcca50e0ac9df0f20a1d7a1d8645e810 Mon Sep 17 00:00:00 2001 From: Vivek Shukla <143773813+Wompie30@users.noreply.github.com> Date: Wed, 20 May 2026 18:58:35 +0530 Subject: [PATCH] fix: polyfill crypto.randomUUID for insecure-context origins (#1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit crypto.randomUUID is restricted to secure contexts (HTTPS or localhost). When RefBoard is served over plain HTTP on a LAN IP (e.g. http://192.168.x.x:8000), the function is undefined and the editor crashes on first ID generation with: Uncaught TypeError: crypto.randomUUID is not a function The frontend calls crypto.randomUUID in ~20 places (uploadManager, SceneManager, Editor, canvas tools, grouping, scene-format, etc.), so a single polyfill at the entry point is the smallest fix. The polyfill uses crypto.getRandomValues — available on insecure origins — to build an RFC 4122 v4 UUID with the correct version/variant bits. It is a no-op when the native function exists, so HTTPS and localhost paths are unchanged. No crypto.subtle usage exists in the source, so randomUUID is the only secure-context API the frontend depends on today. --- frontend/src/main.tsx | 1 + frontend/src/polyfills.ts | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 frontend/src/polyfills.ts diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 2339d59..f72a5e4 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -1,3 +1,4 @@ +import './polyfills'; import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; diff --git a/frontend/src/polyfills.ts b/frontend/src/polyfills.ts new file mode 100644 index 0000000..90db60d --- /dev/null +++ b/frontend/src/polyfills.ts @@ -0,0 +1,21 @@ +// crypto.randomUUID is restricted to secure contexts (HTTPS or localhost). +// On LAN HTTP origins it's undefined, so polyfill via crypto.getRandomValues, +// which is available on insecure origins. +if (typeof crypto !== 'undefined' && typeof crypto.randomUUID !== 'function') { + (crypto as Crypto & { randomUUID: () => string }).randomUUID = function randomUUID() { + const bytes = new Uint8Array(16); + crypto.getRandomValues(bytes); + bytes[6] = (bytes[6] & 0x0f) | 0x40; + bytes[8] = (bytes[8] & 0x3f) | 0x80; + const hex: string[] = []; + for (let i = 0; i < 256; i++) hex.push((i + 0x100).toString(16).slice(1)); + const b = bytes; + return ( + hex[b[0]] + hex[b[1]] + hex[b[2]] + hex[b[3]] + '-' + + hex[b[4]] + hex[b[5]] + '-' + + hex[b[6]] + hex[b[7]] + '-' + + hex[b[8]] + hex[b[9]] + '-' + + hex[b[10]] + hex[b[11]] + hex[b[12]] + hex[b[13]] + hex[b[14]] + hex[b[15]] + ) as `${string}-${string}-${string}-${string}-${string}`; + }; +}