Skip to content

Security: zero mnemonic + keystore in React state on unmount / success #199

@deepanshutr

Description

@deepanshutr

Problem

views/ConnectModal/index.js keeps the freshly-generated mnemonic and uploaded keystore inside React component state (MnemonicSeed, KeystoreFile) for the lifetime of the modal — and beyond, since the parent doesn't explicitly clear them on success or close. They sit in:

  • The React fiber tree (visible to the React DevTools extension).
  • JS heap until GC happens (visible to anyone who can take a heap snapshot).
  • Any retained references through closures created in child components.

The acute leak — console.log(Mnemonic, Password) — was removed in 747b4d0. This issue is the remaining defense-in-depth concern.

Proposed fix

  1. After the wallet-creation flow advances past setStep(4) (mnemonic confirmed) and the parent has captured whatever it needs (encrypted keystore blob), call setMnemonicSeed("") to drop the reference. Same for setKeystoreFile(null) after step 6.
  2. On modal close (close()), explicitly null-out MnemonicSeed + KeystoreFile before unmounting children. Right now closing the modal mid-flow leaves the seed in state until something else triggers a re-render.
  3. For the strings in particular, consider overwriting the variable with a same-length string of zeros before the setState call. JS strings are immutable so this doesn't actually scrub heap memory, but it removes the visible value from the next React render snapshot.
  4. Consider moving the mnemonic from React state into a useRef — refs aren't part of the rendered tree, so they don't show up in DevTools.

Where to look

  • views/ConnectModal/index.js:30MnemonicSeed/KeystoreFile state
  • views/ConnectModal/Mnemonic.js — generates the seed, calls MnemonicSeed(seed) setter
  • views/ConnectModal/MnemonicPassword.js, KeystorePassword.js — receive the values, never clear them after use

Why now

Followup from the audit pass that produced #198. The console.log leaks are fixed; this is the next-tier hardening. Not exploitable without DevTools / extension access, but the defensive cost is low and we already touched these files.

Acceptance

  • After setStep(4), MnemonicSeed no longer holds the seed string in React state.
  • After close(), MnemonicSeed + KeystoreFile are reset.
  • React DevTools snapshot of the connect modal post-success contains no readable seed/key.

Followup to #198.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions