From 47db6a855dee3eb917dc78e5e7ce199681dbc38b Mon Sep 17 00:00:00 2001 From: gonzaloriestra <14979109+gonzaloriestra@users.noreply.github.com> Date: Tue, 26 May 2026 00:50:17 +0000 Subject: [PATCH] [Security] Harden ExtensionServerClient ID generation Replace Math.random() with globalThis.crypto.randomUUID() for cryptographically secure client identifiers. This prevents ID predictability in WebSocket connections. Added a unit test to verify the UUID format. --- .../src/ExtensionServerClient/ExtensionServerClient.test.ts | 6 ++++++ .../src/ExtensionServerClient/ExtensionServerClient.ts | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/ui-extensions-server-kit/src/ExtensionServerClient/ExtensionServerClient.test.ts b/packages/ui-extensions-server-kit/src/ExtensionServerClient/ExtensionServerClient.test.ts index 8ef4ffa1aea..9258905db26 100644 --- a/packages/ui-extensions-server-kit/src/ExtensionServerClient/ExtensionServerClient.test.ts +++ b/packages/ui-extensions-server-kit/src/ExtensionServerClient/ExtensionServerClient.test.ts @@ -163,6 +163,12 @@ describe('ExtensionServerClient', () => { }) describe('initialization', () => { + test('generates a random UUID as id', () => { + const client = new ExtensionServerClient(defaultOptions) + const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i + expect(client.id).toMatch(uuidRegex) + }) + test('connects to the target websocket', async () => { // Create client const client = new ExtensionServerClient(defaultOptions) diff --git a/packages/ui-extensions-server-kit/src/ExtensionServerClient/ExtensionServerClient.ts b/packages/ui-extensions-server-kit/src/ExtensionServerClient/ExtensionServerClient.ts index 507bfb5df73..1484d115272 100644 --- a/packages/ui-extensions-server-kit/src/ExtensionServerClient/ExtensionServerClient.ts +++ b/packages/ui-extensions-server-kit/src/ExtensionServerClient/ExtensionServerClient.ts @@ -32,7 +32,8 @@ export class ExtensionServerClient implements ExtensionServer.Client { private uiExtensionsByUuid: Record = {} constructor(options: DeepPartial = {}) { - this.id = (Math.random() + 1).toString(36).substring(7) + // Security: Use a cryptographically secure random UUID to prevent ID predictability + this.id = globalThis.crypto.randomUUID() this.options = getValidatedOptions({ ...options, connection: {