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
- 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.
- 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.
- 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.
- 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:30 — MnemonicSeed/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
Followup to #198.
Problem
views/ConnectModal/index.jskeeps 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 acute leak —
console.log(Mnemonic, Password)— was removed in 747b4d0. This issue is the remaining defense-in-depth concern.Proposed fix
setStep(4)(mnemonic confirmed) and the parent has captured whatever it needs (encrypted keystore blob), callsetMnemonicSeed("")to drop the reference. Same forsetKeystoreFile(null)after step 6.close()), explicitly null-outMnemonicSeed+KeystoreFilebefore unmounting children. Right now closing the modal mid-flow leaves the seed in state until something else triggers a re-render.useRef— refs aren't part of the rendered tree, so they don't show up in DevTools.Where to look
views/ConnectModal/index.js:30—MnemonicSeed/KeystoreFilestateviews/ConnectModal/Mnemonic.js— generates the seed, callsMnemonicSeed(seed)setterviews/ConnectModal/MnemonicPassword.js,KeystorePassword.js— receive the values, never clear them after useWhy now
Followup from the audit pass that produced #198. The
console.logleaks 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
setStep(4),MnemonicSeedno longer holds the seed string in React state.close(),MnemonicSeed+KeystoreFileare reset.Followup to #198.