Destroying your moneroj for fun and not for profit
TLDR: A lack of unlock time verification on the monero hardware wallets could have allowed a compromised host to permanently lock up a user’s XMR after a transaction. Both Trezor and Ledger patched the issue.
Every monero transaction has a field called
unlock_time. It indicates how
long the outputs have to mature after transaction creation before they can be
spent again. The outputs of a transaction with an
unlock_time of 0 can be
spent immediately, or at least immediately after the normal 10 block maturity
period. If the
unlock_time is 100 blocks above the current block height, the
recipient needs to wait for 100 blocks until he can finally spend the outputs
The maximum number of blocks that can be input is 500’000’000-1, which will
probably be mined in about 1900 years. If the number surpasses this limit, the
unlock_time gets interpreted as Unix time in seconds. Since this is a 64bit
field, it allows locking up coins for over a hundred billion years.
Hardware wallets should protect users against theft, ransom, and loss of their coins by malware on their computers. For a monero wallet using either a Trezor Model T or Ledger Nano S/X, the same expectation needs to hold. Hardware wallets must check all information that is passed to them from the host to ensure that the user’s coins are and remain safe.
The Ledger and Trezor hardware wallets did not check the
when signing a transaction. An adversary with malware on the user’s host
machine could have permanently locked-up the user’s coins with a very high
unlock_time. Since change amounts are not verified on the devices, the entire
balance of the user could be locked-up, even if the user only made a small
Both Trezor and Ledger patched the issue. Trezor could simply patch their
since they already parsed the
unlock_time field as part of their transaction
logic. Both Trezor and Ledger display the raw number on their screen, so block
height and time based
unlock_times display in the same manner.
Sadly, their initial patch introduced more problems. The parsed
which can be any 64-bit number, was cast to a signed 32-bit integer causing an
integer overflow. Depending on the value, the device would either abort or
worse, show the wrong
unlock_time. After some trouble finding the actual
culprit, this additional issue was patched as