Skip to content

[HIGH] SphereProvider.initialize() is not re-entrant: StrictMode / IPFS toggle leaks a second live Sphere instance #453

Description

@KruGoL

Summary

initialize() has no generation counter or cancellation flag, and the mount-effect cleanup only destroys sphereRef.current (still null while an init is in flight). Two overlapping initialize() calls both pass if (sphereRef.current) await destroy(), both build fresh provider bundles (each with its own Nostr transport + IndexedDB connections), both run Sphere.init to completion. The loser of the setSphere race is never destroyed — a zombie wallet stays subscribed to relays with the real identity, keeps processing transfer:incoming/message:dm, writes to the same IndexedDB, and (wallet-api mode) holds a second session under the same deviceId. The app runs under <StrictMode>, so in dev this happens on every load; ConnectPage/IframeAgent guard StrictMode but SphereProvider does not.

Where

src/sdk/SphereProvider.tsx:479. Verified NOT addressed by PR #443.

Fix

Add a monotonic initGenRef (same pattern already used for subscription keys in this file): capture const gen = ++initGenRef.current at the top; after each await check gen !== initGenRef.current and, if stale, destroy the just-created instance and return. Bump the generation in unmount cleanup so a post-unmount init resolution self-destroys.

Found by multi-agent audit @ main b477d4d; adversarially verified. Fix is app-side.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions