Skip to content

Passphrase Prompt - #63

Open
tuxpizza wants to merge 6 commits into
mainfrom
passphrase-ux
Open

Passphrase Prompt#63
tuxpizza wants to merge 6 commits into
mainfrom
passphrase-ux

Conversation

@tuxpizza

@tuxpizza tuxpizza commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Add an updated passphrase prompt on wallet creation.

@tuxpizza
tuxpizza requested a review from MrCyjaneK August 7, 2026 05:36
return null;
}

Future<void> _showBottomSheet(final BuildContext context) async {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security audit finding — MEDIUM

Passphrase bottom-sheet Confirm is unguarded and the sheet is never dismissed — double-fire (or a stale re-tap) silently overwrites the wallet's encrypted .keys backup with a different mnemonic

Severity medium
Confidence high
Category other
CWE CWE-362, CWE-799
Audited f50f4c48 (run eceaea44e9f0)

Affected

  • lib/views/create_wallet.dart L271-L288
  • lib/views/create_wallet.dart L361-L376

What

Introduced by the diff. The new passphrase sheet's Confirm runs await viewModel.createWallet() with no Navigator.pop on success and no in-flight guard (LongPrimaryButton has no busy/disabled state). Two rapid taps call createWallet() twice concurrently: each _createWallet() generates a fresh Mnemonic.create(WordCount.words12), and both write the SAME *.keys file via File(keys).writeAsBytesSync (last-writer-wins). The two executions then each push NewWalletInfoScreen/WalletHome on the root navigator, so the user is shown the first seed on the info pages while the on-disk wallet holds the second mnemonic — after restart the wallet derives keys the user never backed up. Because the modal is isDismissible: false and never popped before createWallet() pushes the next route (via Navigator.of(c!)), the sheet with the filled, masked passphrase and a live Confirm stays mounted underneath the wallet terminal screens (NewWalletInfoScreen/WalletHome are canPop: false, so the buried sheet is not directly reachable on success but is reachable whenever the create flow errors/retries). While the unguarded double-submit class also existed on the base's Continue button, the new sheet is a new creation entry point with the same flaw and the modal-dismissal regression is new.

Remediation

In the Confirm handler, guard against concurrent execution (e.g. a Future<bool> _creating in-flight flag or disable the button while createWallet() runs) and Navigator.pop() the sheet before/after a successful createWallet(). Prefer pushing the post-creation screens only after the sheet route is removed (pop the modal, then navigate).

Posted from the Cake security-audit bot. Use the ❌ False positive button in Slack if this is not a real issue.

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.

2 participants