fix(core): don't rely on crypto.randomUUID for asset ids - #681
Open
maherm wants to merge 1 commit into
Open
Conversation
saveAsset() (called from reference-panel.tsx and local-guide-image.ts, i.e. on every file upload/drop) used crypto.randomUUID() to generate the IndexedDB key. That method requires a secure context (HTTPS or localhost) and is undefined otherwise, so it throws on plain-HTTP origins such as an internal-network deployment reached over a bare IP or hostname - every upload failed immediately there. Switched to nanoid's customAlphabet, which has no secure-context requirement and is already used for ids elsewhere in this package (schema/base.ts). Preferred that over the narrower typeof-check + counter fallback used in packages/nodes/src/cabinet/stack.ts: that counter resets to 0 on every reload, which is fine for stack.ts's transient in-memory compartment ids but not here - asset ids are persisted as IndexedDB keys and as asset://<id> references inside saved/exported scenes, so a colliding fallback could silently overwrite a different asset. nanoid gives the same collision resistance on every code path instead of degrading on insecure origins. Also adds a regression test. There was no existing test for this module because idb-keyval (used here) needs a real indexedDB global, which Bun's test runtime doesn't provide - added fake-indexeddb as a devDependency to fill that gap. The new test stubs crypto.randomUUID as unavailable and asserts saveAsset()/loadAssetUrl() still round-trip correctly; confirmed it fails with the old implementation (TypeError: crypto.randomUUID is not a function) and passes with the fix. Full packages/core suite (957 tests) passes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
saveAsset()(called on every file upload/drop, fromreference-panel.tsxandlocal-guide-image.ts) usedcrypto.randomUUID()to generate the IndexedDB key. That method requires a secure context (HTTPS orlocalhost) and isundefinedotherwise, so it throws on plain-HTTP origins — e.g. an internal-network deployment reached over a bare IP or hostname. Every upload fails immediately there.Switched to
nanoid'scustomAlphabet, which has no secure-context requirement and is already used for ids elsewhere in this package (schema/base.ts). I preferred that over the narrowertypeof-check + counter fallback inpackages/nodes/src/cabinet/stack.ts: that counter resets to 0 on every reload, which is fine forstack.ts's transient in-memory compartment ids but not here — asset ids are persisted as IndexedDB keys and asasset://<id>references inside saved/exported scenes, so a colliding fallback could silently overwrite a different asset.nanoidgives the same collision resistance on every code path instead of degrading on insecure origins.Test plan
packages/core/src/lib/asset-storage.test.ts. There was no existing test for this module becauseidb-keyval(used here) needs a realindexedDBglobal, which Bun's test runtime doesn't provide — addedfake-indexeddbas a devDependency to fill that gap.crypto.randomUUIDas unavailable and assertssaveAsset()/loadAssetUrl()still round-trip correctly. Confirmed it fails against the old implementation (TypeError: crypto.randomUUID is not a function) and passes with the fix.packages/coresuite (957 tests) passes.bun run check(biome) clean across the repo.Note
Low Risk
Small, localized ID generation change with regression tests; no auth or API surface changes, though persisted
asset://id format shifts from UUID to nanoid strings.Overview
Fixes file uploads on plain-HTTP deployments by changing how persisted asset IDs are generated in
saveAsset().saveAsset()previously usedcrypto.randomUUID(), which is unavailable outside a secure context (HTTPS/localhost), so uploads from editor flows that call it could throw immediately on internal HTTP hosts. IDs are now produced withnanoid'scustomAlphabet(16-char alphanumeric), which works in insecure contexts and stays suitable for long-lived IndexedDB keys andasset://references in saved scenes.Test coverage for
asset-storageis added viafake-indexeddbin Bun tests, including a regression that stubscrypto.randomUUIDas missing and asserts save/load still round-trip.Reviewed by Cursor Bugbot for commit cf5611b. Bugbot is set up for automated code reviews on this repo. Configure here.