bugfix: reject incomplete wrapped segwit inputs
What changed, and why it matters
This update fixes a bug in the COLDCARD hardware wallet where a malformed Bitcoin transaction file (PSBT) could slip through if it described a wrapped SegWit input but left out a required piece of data called the redeem script. Without that script, the wallet could not correctly calculate the transaction's fee, which might let an attacker trick the user into approving a transaction that sends far more in fees than intended. The fix makes the wallet reject such malformed files outright.
Treat this as a security-relevant bugfix and include it in the next firmware release. Users should upgrade when available. Wallet software that builds PSBTs for COLDCARD should ensure P2SH-P2WSH inputs always include the redeem script.
Security signals we found
Input-validation hardening for malformed PSBT
Fee-calculation correctness fix
Wrapped SegWit (P2SH-P2WSH) redeem script requirement enforced
Regression test added for missing redeem script rejection
Evidence from the diff
The patch adds a validation check in shared/psbt.py during PSBT input parsing: if an input is identified as P2SH-P2WSH (AF_P2SH with a witness_script present) but the redeem_script is missing, the firmware now raises FatalPSBTIssue(‘Missing redeem script for input #%d’). Previously the code would fall through and set scriptSig to the (possibly None) redeem_script, then continue fee calculation without the redeem script. A regression test in testing/test_multisig.py crafts a P2SH-P2WSH multisig PSBT with a 99,000,000 sat fee and removes the redeem script, confirming the device now refuses to sign with the expected error message.
Changed components
shared/psbt.pytesting/test_multisig.pyCOLDCARD transaction signing flowInspect captured patch +23 / −0
### releases/Next-ChangeLog.md
@@ -8,6 +8,8 @@ This lists the new changes that have not yet been published in a normal release.
disguised with forged key-path metadata or partial signatures.
- Bugfix: Detect and abort transaction signing if a Virtual Disk firmware import
overwrites the reviewed PSBT. Thanks to Huzaifa Jawaid.
+- Bugfix: Reject malformed PSBTs containing P2SH-P2WSH inputs without a redeem
+ script, preventing transactions with an unknown fee from proceeding to approval.
- Bugfix: Restore the ability to view the device-generated seed before adding user
entropy, which was available in the previous dice-roll workflow but was inadvertently
removed in 5.6.1/1.5.1Q. The new **View TRNG Words** menu item displays the full
### shared/psbt.py
@@ -836,6 +836,9 @@ def determine_my_signing_key(self, my_idx, utxo, my_xfp, psbt, cosign_xfp=None):
redeem_script = self.get(ks)
+ if self.addr_fmt == AF_P2SH and self.witness_script and not self.redeem_script:
+ raise FatalPSBTIssue('Missing redeem script for input #%d' % my_idx)
+
self.scriptSig = redeem_script
if not addr_is_segwit and len(redeem_script) == 22 and \
### testing/test_multisig.py
@@ -12,6 +12,7 @@
import time, pytest, os, random, json, shutil, pdb, io, base64, struct, bech32, itertools, re
from psbt import BasicPSBT, BasicPSBTInput, BasicPSBTOutput
from ckcc.protocol import CCProtocolPacker, MAX_TXN_LEN
+from ckcc_protocol.protocol import CCProtoError
from pprint import pprint
from base64 import b64encode, b64decode
from base58 import encode_base58_checksum
@@ -1504,6 +1505,23 @@ def doit(num_ins, num_outs, M, keys, fee=10000, outvals=None,
return doit
+def test_missing_p2sh_p2wsh_redeem_script_rejected(clear_ms, import_ms_wallet,
+ fake_ms_txn, try_sign):
+ clear_ms()
+ M, N = 2, 3
+ keys = import_ms_wallet(M, N, addr_fmt="p2sh-p2wsh", accept=True)
+
+ def remove_redeem_script(psbt):
+ psbt.inputs[0].redeem_script = None
+
+ psbt = fake_ms_txn(1, 1, M, keys, fee=99_000_000, inp_af=AF_P2WSH_P2SH,
+ hack_psbt=remove_redeem_script)
+
+ with pytest.raises(CCProtoError) as exc:
+ try_sign(psbt, False)
+
+ assert "Missing redeem script for input #0" in str(exc.value)
+
@pytest.mark.veryslow
@pytest.mark.unfinalized
@pytest.mark.parametrize('addr_fmt', [AF_P2SH, AF_P2WSH, AF_P2WSH_P2SH])Why this scored 72/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.