From 29d4671e013a0735bfbd22d5e3f42ad4c87cef86 Mon Sep 17 00:00:00 2001 From: yuhp Date: Sat, 21 Feb 2026 09:57:53 +0800 Subject: [PATCH] refactor: use crypto.getRandomValues as primary fallback instead of Math.random --- apps/webclaw/src/lib/utils.ts | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/apps/webclaw/src/lib/utils.ts b/apps/webclaw/src/lib/utils.ts index 0bed9a8..382d581 100644 --- a/apps/webclaw/src/lib/utils.ts +++ b/apps/webclaw/src/lib/utils.ts @@ -7,7 +7,7 @@ export function cn(...inputs: Array) { } export function randomUUID() { - // Check if we're in a secure context with crypto.randomUUID available + // Prefer native randomUUID (requires Secure Context: HTTPS or localhost) if ( typeof window !== 'undefined' && // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition @@ -18,7 +18,24 @@ export function randomUUID() { return window.crypto.randomUUID() } - // Fallback for insecure contexts (e.g. HTTP on LAN) + // Fallback using crypto.getRandomValues (available in all contexts including HTTP) + if ( + typeof crypto !== 'undefined' && + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + crypto.getRandomValues + ) { + const bytes = new Uint8Array(16) + crypto.getRandomValues(bytes) + // Set version 4 (0100) and variant 10xx per RFC 4122 + bytes[6] = (bytes[6] & 0x0f) | 0x40 + bytes[8] = (bytes[8] & 0x3f) | 0x80 + const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join( + '', + ) + return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}` + } + + // Last-resort fallback for environments without crypto support return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { const r = (Math.random() * 16) | 0 const v = c === 'x' ? r : (r & 0x3) | 0x8