verify the signatures of a finalized psbt before copying its fields into an open transaction
What changed, and why it matters
This commit fixes a security gap in Sparrow Wallet when merging two partially-signed Bitcoin transactions (PSBTs). Previously, if a newly loaded PSBT was already finalized, Sparrow would copy its signatures and final transaction data into an open transaction without first checking that those signatures were valid. The change adds a verification step so invalid or malicious finalized PSBT data is rejected before it can overwrite the existing transaction.
Users should upgrade to a Sparrow Wallet release that includes this commit. Developers should review the drongo submodule change to confirm verifyFinalizedSignatures validates all relevant signature types and does not introduce new exceptions that could be abused to stall the merge flow.
Security signals we found
Missing signature verification before accepting finalized PSBT data
Finalized transaction fields could overwrite an unfinalized PSBT's state
Addition of explicit signature verification and exception handling
Submodule bump likely contains the underlying verification implementation
Evidence from the diff
In AppController.handleTransactionMerge, the branch handling a finalized incoming PSBT now calls currentPsbt.verifyFinalizedSignatures(psbt) before currentPsbt.copyFinalizedFields(psbt). A new drongo submodule commit (22d2c90e) presumably adds verifyFinalizedSignatures and/or PSBTSignatureException. The patch prevents finalized PSBT fields from replacing an unfinalized PSBT’s collected signatures unless the finalized PSBT’s signatures are valid for the transaction being built.
Changed components
Sparrow Wallet desktop applicationAppController transaction merge logicdrongo library (PSBT handling submodule)PSBT finalization and signature verification flowInspect captured patch +10 / −4
### drongo
@@ -1 +1 @@
-Subproject commit 10561731c7399c96e53396e91b32f9b5700e0c74
+Subproject commit 22d2c90ef3f7741a604ffd15c91f81cfe611bdb1
### src/main/java/com/sparrowwallet/sparrow/AppController.java
@@ -2209,9 +2209,15 @@ private void handleTransactionMerge(TransactionTabData transactionTabData, PSBT
}
} else {
//If the new PSBT is finalized, copy the finalized fields to the existing unfinalized PSBT
- currentPsbt.copyFinalizedFields(psbt);
- setTabName(tab, name);
- EventManager.get().post(new PSBTFinalizedEvent(currentPsbt));
+ try {
+ //A finalized PSBT is copied rather than combined, so the signatures it provides are verified here before they replace those already collected
+ currentPsbt.verifyFinalizedSignatures(psbt);
+ currentPsbt.copyFinalizedFields(psbt);
+ setTabName(tab, name);
+ EventManager.get().post(new PSBTFinalizedEvent(currentPsbt));
+ } catch(PSBTSignatureException e) {
+ AppServices.showErrorDialog("Invalid PSBT", e.getMessage());
+ }
}
}
Why this scored 69/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.