fix possible db corruption on password removal by reordering database file and row updates
What changed, and why it matters
This commit fixes a bug in Sparrow Wallet that could corrupt the wallet database when a user removes the wallet password/encryption. Previously, the code changed the file's encryption settings before writing the wallet data with the old password, which could leave the database in a broken state. Now, when removing encryption, the wallet data is written first using the current password, and only then is the file encryption removed. When adding or keeping encryption, the file encryption is changed first as before.
Users should upgrade to a Sparrow Wallet version containing this commit, especially if they use or plan to use the password-removal feature. Back up wallet files before changing encryption settings. Developers should consider adding transactional rollback and user-visible error reporting for storage update failures.
Security signals we found
Database corruption possible during password removal
Race condition / ordering bug between file encryption change and data write
Fix involves reordering sensitive cryptographic storage operations
Error handling only logs exception, no rollback or user notification
Evidence from the diff
In DbPersistence.updateWallet(), the order of operations was reordered based on whether encryption is being removed. Previously, updatePassword() was called synchronously before updateExecutor ran update() with the new file password. If newPassword was null (removing encryption), the file password was removed before the data was written with the old password, risking corruption or write failure. The fix computes current and new passwords, then in the executor: if removing encryption, calls update(storage, wallet, currentPassword) first, then updatePassword(storage, encryptionPubKey); otherwise, changes password first then writes with newPassword. This ensures the data is always written with a password matching the current database encryption state.
Changed components
src/main/java/com/sparrowwallet/sparrow/io/db/DbPersistence.javaWallet storage/encryption update pathPassword removal featureInspect captured patch +11 / −2
diff --git a/src/main/java/com/sparrowwallet/sparrow/io/db/DbPersistence.java b/src/main/java/com/sparrowwallet/sparrow/io/db/DbPersistence.java
index ca42ee0..b18bb17 100644
--- a/src/main/java/com/sparrowwallet/sparrow/io/db/DbPersistence.java
+++ b/src/main/java/com/sparrowwallet/sparrow/io/db/DbPersistence.java
@@ -162,11 +162,20 @@ public class DbPersistence implements Persistence {
@Override
public void updateWallet(Storage storage, Wallet wallet, ECKey encryptionPubKey) throws StorageException {
- updatePassword(storage, encryptionPubKey);
+ String newPassword = getFilePassword(encryptionPubKey);
+ String currentPassword = getDatasourcePassword();
updateExecutor.execute(() -> {
try {
- update(storage, wallet, getFilePassword(encryptionPubKey));
+ if(dataSource != null && currentPassword != null && newPassword == null) {
+ //Removing encryption: write data first
+ update(storage, wallet, currentPassword);
+ updatePassword(storage, encryptionPubKey);
+ } else {
+ //Adding encryption or no change: change file first
+ updatePassword(storage, encryptionPubKey);
+ update(storage, wallet, newPassword);
+ }
} catch(Exception e) {
log.error("Error updating wallet db", e);
}
Why this scored 51/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.