BDK relies heavily on the Miniscript language to support arbitrary output descriptors seamlessly.
The Miniscript compiler models arbitrary spending policies and generates an optimized bitcoin script that enforces said policies when executed in the bitcoin network.
Recently a bug has been discovered in the Miniscript type system, which can cause an unsafe bitcoin script to be generated in some cases, described in detail below. Affected UTXOs can be spent by malicious miners without providing any valid signature, effectively bypassing all the signature checks in the script.
We analyzed mainnet blocks starting from the beginning of 2020 and found no transaction spending from a script which is affected by this bug, which leads us to believe that nobody is currenly using this structure in production. Nonetheless, we still recommend upgrading as soon as possible.
# How to check if you are vulnerable
As a rule of thumb, if your descriptor contains a
thresh() with either an
after() inside, then you are probably vulnerable.
Specifically, the following conditions must be met for a descriptor to be vulnerable:
aftermust be a direct child.
oldermust have a wrapper
Moreover, for a miner to be able to steal the funds from a vulnerable script, the timelock (relative or absolute) must be expired.
For example, the descriptor shown in our previous blog post,
wsh(thresh(3,pk(Alice),s:pk(Bob),s:pk(Carol),sdv:older(2))), is actually affected by this vulnerability because it uses a
sdv: wrappers (which is just a shorthand for
s: d: v:).
For the technical details check out the security advisory (opens new window) published by the maintainer of
# Next steps
# If you are affected
If you are affected by the vulnerability, DO NOT SPEND THE FUNDS, as they could be stolen by a malicious miner.
We are in contact with a large mining pool that could include your transaction directly without broadcasting it to the network: contact us and we'll help you out.
Even if you are not affected please update BDK, or at least
rust-miniscript as soon as possible.
0.18.0, released on April 20, addresses this issue by requiring the fixed
6.1.x version of
rust-miniscript. If you need to stay on an older version of BDK, you can run
cargo update to update
rust-miniscript to one
of the non-vulnerable versions:
# Consequences of the update
Since this bug is in the bitcoin script produced by Miniscript, fixing the vulnerabiliy will also make the bitcoin script change: this means that if you don't see your funds in your wallet after the update your script was vulnerable to this bug. Contact us for help sweeping the funds from the old to the newer script.
Also, if your wallet considers a previously-valid descriptor invalid, it also meant it was vulnerable. It can generally be fixed by adding a
n: wrapper to the timelock (i.e.
sdv:older() would become
but that will cause your script to change.
If you were not using a vulnerable script, then nothing should change for you. Please file an issue if you notice other problems after the upgrade.
# Footnote: How we analyzed the blockchain
We used the
blocks_iterator (opens new window) crate to analyze bitcoin blocks starting from early 2020 (initial release date of miniscript) looking for transactions spending from vulnerable scripts.
The tool we used has been published on GitHub (opens new window) and can be run by anyone who wants to verify our claim.
# Correction (2022-04-25)
By re-running the tool on the mainnet blockchain for a second time we were able to find one vulnerable output, created and spent a long time ago (around the initial announcement and release date of Miniscript).
The amount was negligible, so we believe this was a small test performed by somebody to play with Miniscript.