bugfix: restrict HSM BIP322 WIF signing
What changed, and why it matters
This commit fixes a bug in the COLDCARD HSM (High-Security Mode) where signing BIP-322 messages using private keys stored in the device's WIF Store could bypass the message-signing policy. Previously, such signatures may have been allowed even when the policy only permitted specific derivation paths. The fix now requires the HSM policy to explicitly allow 'any' path before WIF Store keys can be used for BIP-322 signing. This is a security-hardening bugfix for a niche but sensitive code path.
Treat as a security bugfix. Review whether prior firmware versions allowed WIF Store BIP-322 signing under restrictive msg_paths policies and consider issuing an advisory or firmware update note for HSM users. No immediate emergency response appears warranted, but users relying on HSM policy restrictions should update.
Security signals we found
Bugfix explicitly described as restricting HSM signing policy
Adds authorization check before WIF Store key usage in BIP-322 message signing
Raises ValueError to block disallowed signing path
Adds regression test for the restriction
Changelog frames change as a 'Bugfix' with security-relevant behavior
Evidence from the diff
In shared/hsm.py, the transaction approval logic now checks whether any input’s required public key is present in psbt.wif_store. If so, and the HSM policy’s msg_paths does not include ‘any’, it raises ValueError(‘WIF Store message signing requires any path’). This closes a gap where BIP-322 PSBTs using WIF-stored keys could be signed under a restrictive msg_paths policy. A regression test was added in testing/test_hsm.py to verify the restriction and that ‘any’ path permits it.
Changed components
shared/hsm.pyHSM message-signing policy enforcementBIP-322 PSBT signing flowWIF Store key handlingInspect captured patch +25 / −1
### releases/Next-ChangeLog.md
@@ -18,7 +18,8 @@ This lists the new changes that have not yet been published in a normal release.
## 5.6.x - 2026-0x-xx
-- tbd
+- Bugfix: Require unrestricted HSM message-signing policy when signing BIP-322
+ messages with WIF Store keys.
# Q Specific Changes
### shared/hsm.py
@@ -897,6 +897,12 @@ async def approve_transaction(self, psbt, psbt_sha, story):
if not inp.required_key:
continue
+ required_keys = inp.required_key if inp.is_multisig else [inp.required_key]
+ if any(pk in psbt.wif_store for pk in required_keys):
+ if 'any' not in self.msg_paths:
+ raise ValueError("WIF Store message signing requires any path")
+ continue
+
if inp.is_multisig:
paths = [
keypath_to_str(inp.subpaths[pk])
### testing/test_hsm.py
@@ -953,6 +953,23 @@ def test_bip322_psbt_uses_msg_sign_policy(quick_start_hsm, change_hsm, attempt_p
attempt_psbt(psbt, "Message signing not permitted")
+def test_bip322_wif_requires_any_msg_path(quick_start_hsm, change_hsm, attempt_psbt,
+ bip322_txn, settings_set, settings_remove):
+ settings_remove("wifs")
+ key = PrivateKey(prandom(32))
+ pubkey = key.K.sec()
+ settings_set("wifs", [(pubkey.hex(), bytes(key).hex())])
+ psbt, _ = bip322_txn(
+ [["p2wpkh", None, None, pubkey]], msg=b"HSM WIF BIP-322")
+
+ quick_start_hsm(DICT(msg_paths=["m/0"], warnings_ok=True))
+ attempt_psbt(psbt, "WIF Store message signing requires any path")
+
+ change_hsm(DICT(msg_paths=["any"], warnings_ok=True))
+ attempt_psbt(psbt)
+ settings_remove("wifs")
+
+
def test_bip322_por_psbt_uses_msg_sign_policy(quick_start_hsm, change_hsm, attempt_psbt,
bip322_txn):
psbt, _ = bip322_txn([Why this scored 62/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.