warn before creating a keystore from a scanned seed with an invalid checksum
What changed, and why it matters
This change adds a warning when a user scans a QR code containing a seed phrase whose checksum is invalid. Previously, Sparrow would silently create a wallet keystore from the bad seed. With a bad checksum, other wallets will reject the same seed words, so any bitcoin sent to that wallet could become unrecoverable from the backup. The patch asks the user to confirm before proceeding.
Treat as a low-to-moderate reliability/security improvement. Users should upgrade to benefit from the warning. No immediate incident response is indicated, but users who previously imported seeds via QR should verify their backups produce valid checksums and match their wallet fingerprints.
Security signals we found
User-facing warning added for invalid mnemonic checksum
Prevents silent creation of unrecoverable keystore from scanned seed
Funds sent to derived addresses may be unrecoverable if seed checksum is invalid
No cryptographic enforcement; user can still override the warning
Evidence from the diff
In KeystoreController.scanXpubQR(), after decoding a QR result that contains a seed, the code now calls result.seed.check() before deriving the keystore. If that throws MnemonicException (invalid checksum/BIP39 checksum failure), a warning dialog is shown explaining the risk and asking whether to continue. Only if the user clicks YES does the existing keystore creation and UI population proceed. This is a defensive UX fix, not a cryptographic change.
Changed components
src/main/java/com/sparrowwallet/sparrow/wallet/KeystoreController.javascanXpubQR() methodSeed QR import flowInspect captured patch +10 / −0
### src/main/java/com/sparrowwallet/sparrow/wallet/KeystoreController.java
@@ -656,6 +656,16 @@ public void scanXpubQR(ActionEvent event) {
AppServices.showErrorDialog("Missing Script Type", "QR Code did not contain any information for the " + getWalletForm().getWallet().getScriptType().getDescription() + " script type.");
} else if(result.seed != null) {
try {
+ try {
+ result.seed.check();
+ } catch(MnemonicException e) {
+ Optional<ButtonType> optType = AppServices.showWarningDialog("Invalid checksum", "The scanned seed does not have a valid checksum, which usually indicates a scanning or transcription error. " +
+ "Other wallets will not accept it, so any funds sent to this keystore may not be recoverable from a backup of these words.\n\nUse this seed anyway?", ButtonType.NO, ButtonType.YES);
+ if(optType.isEmpty() || optType.get() != ButtonType.YES) {
+ return;
+ }
+ }
+
Keystore keystore = Keystore.fromSeed(result.seed, getWalletForm().getWallet().getPolicyType(), getWalletForm().getWallet().getScriptType().getDefaultDerivation());
fingerprint.setText(keystore.getKeyDerivation().getMasterFingerprint());
derivation.setText(keystore.getKeyDerivation().getDerivationPath());Why this scored 44/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.