skip malformed silent payment entries rather than aborting the scan batch
What changed, and why it matters
This commit changes how Sparrow Wallet handles data received from an Electrum server about silent payments. Previously, if one entry in a batch was malformed, the entire scan batch would abort. Now, the wallet logs a warning and skips only the bad entry. This makes the wallet more resilient to bad server data, but also means a malicious or buggy server could silently feed malformed entries and have them ignored rather than trigger a visible failure. There is no direct evidence in the commit that this is exploitable to steal funds, but it removes a fail-stop behavior.
Treat this as a hardening/reliability change rather than a confirmed vulnerability. Review whether silently skipping malformed silent payment entries could allow a malicious Electrum server to withhold valid payments from the wallet's scan results. Consider whether skipped entries should be surfaced to the user or retried, and whether the 33-byte check and exception handling are sufficient. No urgent patch action is indicated by the commit alone.
Security signals we found
Changes error handling from abort to continue on malformed external input
Adds input length validation (33-byte tweak key)
Catches NullPointerException, which can mask unexpected data shape
Catches broader exception type (IllegalArgumentException) downstream
No explicit security rationale or advisory referenced in commit
Evidence from the diff
In ElectrumServer.processSilentPaymentBatch(), the code previously assumed SilentPaymentsTx entries contained valid tx_hash and tweak_key values. The patch wraps parsing in a try/catch that catches NullPointerException and ProtocolException, logs a warning, and continues to the next entry. It also validates that the decoded tweak key is exactly 33 bytes. A second catch block lower in the method now also catches IllegalArgumentException in addition to InvalidSilentPaymentException. The change shifts behavior from abort-on-error to skip-on-error for silent payment scan batches.
Changed components
src/main/java/com/sparrowwallet/sparrow/net/ElectrumServer.javaSilent payment batch scanningElectrum server client parsingInspect captured patch +15 / −3
### src/main/java/com/sparrowwallet/sparrow/net/ElectrumServer.java
@@ -1619,8 +1619,20 @@ public Set<WalletNode> processSilentPaymentBatch(Wallet wallet, List<SilentPayme
//batch and needs its spent-input nodes identified.
Set<Sha256Hash> alreadyInWallet = new HashSet<>();
for(SilentPaymentsTx entry : entries) {
- Sha256Hash txid = Sha256Hash.wrap(entry.tx_hash);
- tweakMap.putIfAbsent(txid, Utils.hexToBytes(entry.tweak_key));
+ Sha256Hash txid;
+ byte[] tweakKey;
+ try {
+ txid = Sha256Hash.wrap(entry.tx_hash);
+ tweakKey = Utils.hexToBytes(entry.tweak_key);
+ if(tweakKey.length != 33) {
+ throw new ProtocolException("Tweak key must be 33 bytes, not " + tweakKey.length);
+ }
+ } catch(NullPointerException | ProtocolException e) {
+ log.warn("Skipping malformed silent payments entry " + entry + ": " + e);
+ continue;
+ }
+
+ tweakMap.putIfAbsent(txid, tweakKey);
BlockTransaction existing = wallet.getWalletTransaction(txid);
if(existing != null) {
transactionMap.put(txid, existing);
@@ -1691,7 +1703,7 @@ public Set<WalletNode> processSilentPaymentBatch(Wallet wallet, List<SilentPayme
}
}
}
- } catch(InvalidSilentPaymentException e) {
+ } catch(InvalidSilentPaymentException | IllegalArgumentException e) {
log.warn("Invalid silent payment tweak for tx " + txid + " — skipping", e);
}
}Why this scored 42/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.