Security Advisory: Miniscript MINIMALIF Bug

By Alekos Filini on 4/20/2022 - Tags: Miniscript, Security

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 older() or after() inside, then you are probably vulnerable.

Specifically, the following conditions must be met for a descriptor to be vulnerable:

  1. thresh fragment.
  2. older or after must be a direct child.
  3. older must have a wrapper d: around it.

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 thresh() containing an older() with 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 rust-miniscript.

# 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.

# Everybody

Even if you are not affected please update BDK, or at least rust-miniscript as soon as possible.

BDK version 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:

  • 6.1.0
  • 5.2.0
  • 4.1.0
  • 3.1.0
  • 2.1.0
  • 1.1.0

# 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 sndv:older()), 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.

We would like to thank sanket1729 (opens new window) and RCasatta (opens new window) for their help implementing and running the tool on the bitcoin mainnet blockchain.

# 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.