What changed, and why it matters
This commit fixes a bug in COLDCARD's 'deltamode' duress feature. Delta mode is meant to let a thief who knows a slightly wrong PIN sign transactions with corrupted signatures that look valid but don't actually protect any bitcoin. The bug was that the fake signature was produced from a fixed, predictable placeholder instead of from the real transaction data. A security research team claims this predictability could let an attacker who captures two such signatures recover the wallet's private keys, potentially stealing all funds. The patch makes the corrupted signature depend on the real transaction hash, removing that mathematical shortcut.
Treat this as a security fix and ensure firmware builds containing this commit are deployed. Users who may have used delta mode or had a device with a known slightly-wrong PIN exposed should rotate to a new seed and avoid relying on older delta-mode signatures. Review whether the delta-mode feature's security design should be retained given the disclosed attack.
Security signals we found
duress/deltamode bypass
predictable signing digest replaced with transaction-dependent digest
private-key recovery claimed by independent researchers
same-day fix linked to research disclosure
Evidence from the diff
In shared/psbt.py the signing digest for delta mode was previously hardcoded to bytes(range(32)) before signing, meaning the same nonce/message relationship was used regardless of the PSBT. The patch moves the real sighash computation ahead of the deltamode branch and then applies sha256d to that real digest, so the corrupted signature is now transaction-dependent. The referenced research disclosure frames this as a critical private-key recovery vulnerability (VULN-023) tied to two known delta-mode signatures.
Changed components
shared/psbt.pyCOLDCARD delta-mode duress signing pathInspect captured patch +9 / −9
diff --git a/shared/psbt.py b/shared/psbt.py
index daba9f2..27d1010 100644
--- a/shared/psbt.py
+++ b/shared/psbt.py
@@ -2045,19 +2045,19 @@ class psbtObject(psbtProxy):
# track wallet usage
OWNERSHIP.note_subpath_used(inp.subpaths[which_key])
+ if not inp.is_segwit:
+ # Hash by serializing/blanking various subparts of the transaction
+ digest = self.make_txn_sighash(in_idx, txi, inp.sighash)
+ else:
+ # Hash the inputs and such in totally new ways, based on BIP-143
+ digest = self.make_txn_segwit_sighash(in_idx, txi,
+ inp.amount, inp.scriptCode, inp.sighash)
+
if sv.deltamode:
# Current user is actually a thug with a slightly wrong PIN, so we
# do have access to the private keys and could sign txn, but we
# are going to silently corrupt our signatures.
- digest = bytes(range(32))
- else:
- if not inp.is_segwit:
- # Hash by serializing/blanking various subparts of the transaction
- digest = self.make_txn_sighash(in_idx, txi, inp.sighash)
- else:
- # Hash the inputs and such in totally new ways, based on BIP-143
- digest = self.make_txn_segwit_sighash(in_idx, txi,
- inp.amount, inp.scriptCode, inp.sighash)
+ digest = ngu.hash.sha256d(digest)
# The precious private key we need
pk = node.privkey()
Why this scored 80/100
Evidence and disclosure record
Verified links used to place this patch in context. External claims remain attributed to their publishers.
Coldcard Delta PIN Bitcoin Private Key Recovery Vulnerability
Research disclosure describing private-key recovery from two Delta-mode transaction signatures and identifying the issue as critical.
Coldcard v5.6.0 Post-Hotfix Analysis and Disclosure History
Follow-up disclosure history linking VULN-023 to same-day fix commit fcd848d8 and documenting the attribution record.
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.