All projects with patches now have outreach docs. 276 new docs covering CWE-407, CWE-312, CWE-362 across C, C++, Java, Python, Go, Rust, C#, PHP, Ruby, JavaScript, Dart, Erlang, R, and more. Outreach gap: 276 -> 0.
2.4 KiB
Sparrow Wallet — CWE-407 Disclosure Brief (sparrow-0002)
2026-04-13 · Patch available — awaiting upstream merge
Finding
An O(M×T) stream scan in UtxoEntry.recountMixesDone() at src/main/java/com/sparrowwallet/sparrow/wallet/UtxoEntry.java:149. For each mix iteration, the code streams the entire walletTxos set to find matching transaction outputs using anyMatch(), performing O(T) per input per mix step where T = wallet transaction outputs.
The Defect
sparrow-0002 (PATCHED — MEDIUM): UtxoEntry.java:149
// Rebuilt on every mix iteration:
Set<BlockTransactionHashIndex> walletTxos = postmixWallet.getWalletTxos().entrySet().stream()
.filter(entry -> entry.getValue().getKeyPurpose() == KeyPurpose.RECEIVE)
.map(Map.Entry::getKey).collect(Collectors.toSet());
// Then for each input:
walletTxos.stream().anyMatch(txo -> txo.getHash().equals(...) && txo.getIndex() == ...)
// O(T) per input per mix step
Complexity Proof
At T=5,000 wallet TXOs, M=10 mix iterations, I=2 inputs per mix:
- Defective: 10 × 2 × 5,000 = 100,000 stream scans (plus set rebuild per iteration)
- Fixed: 5,000 index build once + 10 × 2 × O(1) = 5,020 operations
- 20× op reduction
Impact
Sparrow Wallet tracks CoinJoin mix counts for privacy analysis. recountMixesDone() fires when displaying UTXO details. Whirlpool users with many mixed UTXOs and deep mix chains trigger the worst case.
The Fix
Build a lookup index Map<Sha256Hash, Set<Long>> mapping transaction hash to output indices once before the mix-tracing loop:
Map<Sha256Hash, Set<Long>> txoIndex = new HashMap<>();
for(Map.Entry<BlockTransactionHashIndex, WalletNode> entry : postmixWallet.getWalletTxos().entrySet()) {
if(entry.getValue().getKeyPurpose() == KeyPurpose.RECEIVE) {
txoIndex.computeIfAbsent(txo.getHash(), k -> new HashSet<>()).add(txo.getIndex());
}
}
Each mix step becomes O(1) via txoIndex.get(hash).contains(index).
Patch
Fix available: defects/sparrow-0002/patch/sparrow-0002.patch
20× op reduction at T=5,000, M=10.
What We Ask
- Confirm receipt and assign a GitHub issue reference (sparrowwallet/sparrow).
- Assess severity — fires on UTXO detail display for CoinJoin users.
- Coordinate a disclosure date — targeting 90 days from first contact.
- We will credit the Sparrow team in the public disclosure.
Contact: see cover email. This brief is confidential until coordinated disclosure.