ledger: handle script path signatures
What changed, and why it matters
This commit updates the Ledger hardware wallet driver in HWI so it can correctly store Taproot script-path signatures in a PSBT, not just key-path signatures. Previously, the code had a placeholder that always treated any Taproot signature as a key-path signature. For users spending via a Taproot script path (for example, a multisig or timelock branch), the signature would have been placed in the wrong field, likely causing the PSBT to be invalid or incomplete. There is no direct evidence in the commit of an exploitable vulnerability; it appears to be a correctness/functional fix for an unimplemented feature.
Treat as a routine correctness fix. Users relying on Ledger + HWI for Taproot script-path spends should upgrade to a version containing this commit. Review whether any downstream consumers of the PSBT relied on the previous (incorrect) tap_key_sig placement. No urgent security response is indicated by the diff alone.
Security signals we found
Previously unimplemented TODO for script-path signatures
Incorrect PSBT field assignment for Taproot script-path spends
Functional gap that could produce an invalid or incomplete PSBT
No explicit security framing by the vendor in commit message
Evidence from the diff
In hwilib/devices/ledger.py, the LedgerClient.sign_tx method previously set psbt_in.tap_key_sig for every witness version 1 (Taproot) signature returned by the device, with a TODO noting that script-path signatures were not handled. The patch distinguishes the two cases: if yielded.tapleaf_hash is None, the signature is a key-path signature and goes to tap_key_sig; otherwise it is a script-path signature and is stored in psbt_in.tap_script_sigs[(pubkey, tapleaf_hash)]. This aligns the driver with BIP-371 PSBT fields for Taproot. The change is small and targeted, and no other code paths are modified.
Changed components
hwilib/devices/ledger.pyLedgerClient.sign_txTaproot / witness version 1 signature handlingInspect captured patch +5 / −3
diff --git a/hwilib/devices/ledger.py b/hwilib/devices/ledger.py
index a3ff3c0..fdb6b6d 100644
--- a/hwilib/devices/ledger.py
+++ b/hwilib/devices/ledger.py
@@ -363,9 +363,11 @@ class LedgerClient(HardwareWalletClient):
is_wit, wit_ver, _ = utxo.is_witness()
if is_wit and wit_ver >= 1:
- # TODO: Deal with script path signatures
- # For now, assume key path signature
- psbt_in.tap_key_sig = yielded.signature
+ if yielded.tapleaf_hash is None:
+ psbt_in.tap_key_sig = yielded.signature
+ else:
+ psbt_in.tap_script_sigs[(yielded.pubkey, yielded.tapleaf_hash)] = yielded.signature
+
else:
psbt_in.partial_sigs[yielded.pubkey] = yielded.signature
Why this scored 40/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.