Bitcoin Core Patched PSBT Signing. Your Wallet Hasn't Caught Up.
CryptoWhale
Last September I sat in a Tallinn co-working space, staring at a PSBT file that told me one story while its signature told another.
I had spent two weeks building a small multisig treasury for a group of remote workers β six signers, two hardware devices, one coordinator on a laptop. Everything looked right in the interface. The recipient address was correct. The amount was correct. Then I ran the raw transaction through a debugger and found a signature that did not actually bind to the output I believed I was paying. It took me another three weeks to understand why I was wrong, and by then I had already switched the whole setup to SIGHASH_ALL and quietly moved on, embarrassed that I had been standing on a crack without noticing.
So when Bitcoin Core merged a fix to master on September 25, I felt that specific nausea. Bitcoin Optech surfaced the change on October 2. As of October 4, there is no release, no backport, no version number. Just a quiet patch to an edge case older than most of the wallets that inherit it.
PSBT β Partially Signed Bitcoin Transactions, defined in BIP-174 β is the connective tissue of modern Bitcoin custody. It lets a coordinator pass a half-finished transaction to a hardware device, then to an offline laptop, then to a cosigning service and back, each party adding signatures without ever needing the others' keys. Coldcard, Sparrow, Specter, Ledger, Trezor, and nearly every enterprise multisig platform speak it fluently.
SIGHASH_SINGLE is one signing mode inside that flow. Where SIGHASH_ALL commits your signature to every input and output in a transaction, SIGHASH_SINGLE binds input N to output N β one input, one output, precise authorization. It exists so you can fund a transaction while committing only to your own slice. Elegant in theory, rare in practice, and dangerous in exactly one situation: when there is no output at position N.
BIP-174 anticipated this. It explicitly instructs signers to reject unacceptable signature modes and recommends SIGHASH_ALL when no alternative is specified. The standard did its job. The implementation did not fully follow β and that gap is what Core just closed.
Here is the mechanic, and it matters because it is not a private key leak.
When a PSBT requests SIGHASH_SINGLE for an input with no matching output, the protection that normally binds your signature to a destination fails β differently depending on what kind of coin you are spending.
For legacy inputs, the failure is brutal. The signature hash collapses to a fixed constant β 0x0000...0001, the same value Bitcoin has produced in this edge case since the earliest days of the codebase. A signature over that constant is not bound to any output at all. If the same key controls other UTXOs, that signature can be replayed across them. This is not hypothetical: CVE-2020-14199 described the same class of problem inside hardware wallet flows five years ago, and the ecosystem has been quietly patching different surfaces of it ever since.
For SegWit v0 inputs, the picture is less catastrophic but still wrong. The signature stays bound to the specific coin and amount being spent β so an attacker cannot simply redirect funds to their own address β but the target output still is not cryptographically tied to what the signer approved. The signature is valid. It just is not yours in the way you think it is.
The fix itself is revealing. The old check lived in the raw transaction signing interface, which already rejected this edge case. The new code moves that check into the shared signing logic β the path that PSBT actually travels through. Same protection, one layer deeper. Critically, it blocks only the affected legacy and SegWit v0 inputs while letting other valid inputs in the same PSBT proceed. That restraint matters: a blunter patch would have broken legitimate multi-input transactions and pushed developers toward workarounds.
Taproot and SegWit v1 are unaffected. The scope is legacy and v0, nothing more. And the release status is the part almost nobody is pricing: merged to master, not shipped, no backport confirmed as of October 4.
What strikes me, sitting with this, is that the bug was never really about cryptography. It was about a semantic gap β the space between what a wallet shows you and what a signature actually commits to. The interface says pay this address. The cryptography says I authorize something whose shape I cannot fully verify. Most of the time these agree. In this edge case, they quietly diverge, and the user has no way to notice.
Here is the uncomfortable reading, and it is not the one making the rounds.
Everyone is treating this as a Core story. It is not. Core already did its job β the source is plugged, the code is merged, the reference implementation is safe. The actual risk lives downstream, in a fragmented, voluntary, slow-moving ecosystem of wallets and hardware vendors with no obligation to update on anyone's schedule.
We didn't wait β we shipped our own guard. That is what a well-run wallet team should be able to say right now. The ones who cannot are the exposed ones, and they are the majority. Nothing in the October 4 picture suggests any of them have moved. No firmware announcements, no coordinator updates, no public advisory from the major signing devices. The window between upstream fix and downstream adoption is where the residual risk lives, and it can stay open for months.
There is a second reading, deeper and more durable. This is not really a bug report. It is a reminder that cryptographically valid and user authorized are two different claims, and the Bitcoin wallet stack has spent a decade letting the first stand in for the second. The same divergence appears wherever we outsource verification to a screen β the same instinct that lets people trust a sequencer's word for a Layer 2's state, or treat a channel balance on a Lightning node as if it were settlement. The signature is real. Whether it means what you were told it means is a separate question we rarely ask.
Bitcoin Core fixed its side on September 25. Your wallet, your hardware device, your cosigning service β none of them have necessarily moved, and no release forces them to.
So here is the question I keep circling back to, and I do not have a clean answer: if a signature is valid but does not bind what you think you authorized, who exactly approved the payment? You did, in the eyes of every node on the network. But whether that counts as consent is a question code cannot answer and that we have barely started to ask.