Skip to content

fix(db): fall back to crypto.getRandomValues when randomUUID is unavailable#1557

Draft
spokodev wants to merge 1 commit into
TanStack:mainfrom
spokodev:fix/safe-random-uuid-non-secure-context
Draft

fix(db): fall back to crypto.getRandomValues when randomUUID is unavailable#1557
spokodev wants to merge 1 commit into
TanStack:mainfrom
spokodev:fix/safe-random-uuid-non-secure-context

Conversation

@spokodev
Copy link
Copy Markdown

Problem

crypto.randomUUID() is restricted to secure contexts per the Web Crypto spec, so it is unavailable on pages served over plain HTTP from a non-localhost host (for example a dev server reached via a LAN IP). @tanstack/db calls it directly from collections, transactions, mutations, local-only, and local-storage, so the first write throws

TypeError: crypto.randomUUID is not a function

before user code can handle it. crypto.getRandomValues() remains available in non-secure contexts, so a v4 UUID is still reachable; we just have to assemble it ourselves when the higher-level API is missing.

Repro

http://<LAN-IP>:<port>
window.isSecureContext // false
typeof crypto.randomUUID // "undefined"
typeof crypto.getRandomValues // "function"
import { createCollection, localOnlyCollectionOptions } from '@tanstack/db'

const collection = createCollection(
  localOnlyCollectionOptions({
    id: 'items',
    getKey: (item) => item.id,
  }),
)

collection.insert({ id: '1' }) // throws TypeError: crypto.randomUUID is not a function

Fix

Add a safeRandomUUID() helper in packages/db/src/utils.ts:

  1. Use crypto.randomUUID() when available (the common case).
  2. Fall back to RFC 4122 v4 generation via crypto.getRandomValues() with the version/variant bits set per spec §4.4.
  3. Throw an explicit Error if neither Web Crypto API is available.

Replace the seven direct call sites with the helper:

  • packages/db/src/collection/index.ts (default collection id)
  • packages/db/src/collection/mutations.ts (insert / update / delete mutation ids; three sites)
  • packages/db/src/local-only.ts (local-only collection id)
  • packages/db/src/local-storage.ts (version-tracking uuid)
  • packages/db/src/transactions.ts (transaction id)

The issue body listed four files; while replacing those I also found three additional crypto.randomUUID() call sites in mutations.ts (the per-operation mutationId) and one in local-storage.ts that have the same failure mode, and rolled them into the helper as well so the fallback is consistent across @tanstack/db.

Tests

packages/db/tests/safe-random-uuid.test.ts covers both axes:

  • Delegate path: when crypto.randomUUID exists, the helper returns its value unchanged and the stub is called exactly once.
  • Fallback path: when only crypto.getRandomValues is present, the result matches a strict RFC 4122 v4 regex (/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/).
  • Fallback uniqueness: two successive fallback calls with deterministic but distinct byte input produce different UUIDs, ensuring the helper does not collapse to a constant when randomUUID is missing.
  • No crypto at all: throws an explicit error mentioning the Web Crypto API.
  • Partial crypto ({} object, no randomUUID, no getRandomValues): same explicit error, so we never silently fall through to native crypto.

All five new tests pass with the patched helper (pnpm --filter @tanstack/db test). The pre-existing 163 test failures on main (localStorage.getItem is not a function in union-all.test.ts and related jsdom interactions) are not introduced by this change; the new test count of 2213 passed matches 2208 baseline + 5 new.

Lint clean (pnpm --filter @tanstack/db lint, no new warnings). Build clean (pnpm --filter @tanstack/db build).

Closes #1541

Note on disclosure

Bug discovery and reproduction were independent of this contributor (issue author @kj55-dev filed a clean writeup with a suggested fix). I implemented the helper, located the additional call sites in mutations.ts and local-storage.ts, wrote the tests, and reviewed every change. AI assistance was used while drafting parts of the test cases and this PR body, in line with the AGENTS.md guidance in the repo.

…ilable

`crypto.randomUUID()` is restricted to secure contexts in browsers, so it
is unavailable on pages served over plain HTTP from a non-localhost host,
for example a dev server reached via a LAN IP. `@tanstack/db` was calling
it directly from transactions, mutations, local-storage, local-only and
the default collection-id path, so the first write would throw
`TypeError: crypto.randomUUID is not a function` before user code could
handle it.

Centralise UUID generation in `safeRandomUUID()` (in `utils.ts`) which:

- delegates to `crypto.randomUUID()` when present (the common case),
- falls back to RFC 4122 v4 generation via `crypto.getRandomValues()`
  when it is not, with the version/variant bits set per spec,
- throws an explicit Error if neither Web Crypto API is available.

Replace the seven direct call sites with `safeRandomUUID()` and add unit
tests covering the delegate path, the fallback path (validating a v4
shape), uniqueness across calls in fallback mode, and both error paths
when crypto is missing or partial.

Closes TanStack#1541
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 25, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c46a7ccd-ee8b-43af-ac39-9c7730aae06c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

@tanstack/db assumes crypto.randomUUID exists in non-secure browser contexts

1 participant