fix(gateway): preserve AsyncEventQueue error state & use crypto random for client IDs#152
Conversation
…m for IDs Two fixes in GatewayBrowserClient.ts: 1. **AsyncEventQueue error state preserved (issue OpenBMB#128)** The `next()` method was clearing `this.error` after the first read, causing subsequent consumers to get `{done: true}` instead of the error. This broke WebSocket reconnection retry logic — after the first consumer saw the error, all retries silently got "done" and stopped trying. Fix: keep `this.error` persistent. Every call to `next()` after a failure now correctly rejects with the same error. 2. **Non-crypto random fallback replaced (issue OpenBMB#136)** When `crypto.randomUUID()` is unavailable, the fallback used `Math.random()` for token/ID generation — producing predictable tokens exploitable in WebSocket reconnection scenarios. Fix: use `crypto.getRandomValues(new Uint8Array(16))` converted to hex for the fallback path. Only falls through to `Math.random()` when no crypto API exists at all (extremely rare in modern runtimes). Verified: `npx tsc --noEmit -p tsconfig.json` passes clean. Closes: OpenBMB#128, OpenBMB#136 🤖 Generated with [Qoder][https://qoder.com]
|
Hi! Two small but impactful fixes in AsyncEventQueue error swallowing (#128): The Non-crypto random for client IDs (#136): Both changes are localized and don't alter the public API. Let me know if anything needs tweaking! |
Summary
This PR fixes two bugs in
src/web/client/GatewayBrowserClient.ts:1.
AsyncEventQueuesilently swallows errors after first read (Closes #128)Root cause: In
next(), the error field was cleared (this.error = undefined) immediately after the first consumer read it. Any subsequent retry or reconnection attempt would receive{ done: true }instead of the original error, making the failure invisible.Fix: The error is no longer cleared on read — it is preserved so that all consumers (including retries) see the rejection. The queue's
close()andthrow()methods still function as before.2. Non-cryptographic
Math.random()used for security-sensitive client IDs (Closes #136)Root cause: The fallback ID generation used
Math.random(), which is predictable and unsuitable for tokens that may be used in authentication or session identification contexts.Fix: Replaced with
crypto.getRandomValues()(available in all modern browsers and Node.js 19+). A 16-byte hex string is generated from cryptographically secure random bytes.Changes
GatewayBrowserClient.ts—AsyncEventQueue.next(): removedthis.error = undefinedGatewayBrowserClient.ts—generateClientId(): replacedMath.random()withcrypto.getRandomValues()Test plan
AsyncEventQueueerror is visible to multiple consumers (read error twice, both should reject)generateClientId()produces hex-suffixed IDs in browser and Node.js environmentsnpx tsc --noEmit -p tsconfig.json🤖 Generated with [Qoder][https://qoder.com]