ENV-2282: fixed taproot sighahes after segwit sighashes
What changed, and why it matters
This is a one-line fix in the Bitcoin transaction signing code of the Foundation Passport hardware wallet. When signing a Taproot transaction immediately after signing a SegWit transaction, the wallet could reuse cached intermediate hash values that were not fully initialized for Taproot. That could cause the wallet to compute an incorrect transaction fingerprint (sighash), which in rare cases might lead to an invalid signature or, more seriously, a signature that does not protect all the transaction details it should. The fix forces the wallet to rebuild those cached hashes if any of the required Taproot hash fields are missing.
Treat this as a security-relevant firmware bug. Verify that the fix fully invalidates the sighash cache when switching between SegWit and Taproot signing modes, and audit other cached fields (hashSequences, hashOutputs, etc.) for similar partial-initialization issues. Users should install the firmware release containing this commit before signing Taproot transactions that follow SegWit transactions in the same session.
Security signals we found
Incorrect cached hash reuse across signing contexts
Taproot sighash completeness check bypass
State not reset between SegWit and Taproot PSBT processing
Potential signature over incomplete transaction data
Evidence from the diff
In ports/stm32/boards/Passport/modules/psbt.py, the Taproot sighash path checked only self.hashPrevouts before recomputing the cached hashes hashPrevouts, hashAmounts, and hashScriptPubkeys. After a SegWit signing operation these fields may be partially populated (hashPrevouts set, but hashAmounts/hashScriptPubkeys not set for the Taproot path). The patch changes the guard to recompute whenever any of the three required hashes is None, ensuring the BIP-341 sighash is computed from complete data. The bug is a state-carryover defect between PSBT signing operations.
Changed components
ports/stm32/boards/Passport/modules/psbt.pyTaproot (BIP-341) transaction signingPSBT sighash cacheInspect captured patch +1 / −1
diff --git a/ports/stm32/boards/Passport/modules/psbt.py b/ports/stm32/boards/Passport/modules/psbt.py
index 1dbdaf0..f33883a 100644
--- a/ports/stm32/boards/Passport/modules/psbt.py
+++ b/ports/stm32/boards/Passport/modules/psbt.py
@@ -1678,7 +1678,7 @@ class psbtObject(psbtProxy):
assert sighash_type == SIGHASH_DEFAULT
- if self.hashPrevouts is None:
+ if self.hashPrevouts is None or self.hashAmounts is None or self.hashScriptPubkeys is None:
# First time thru, we'll need to hash up this stuff.
prevouts = trezorcrypto.sha256()
Why this scored 70/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.