The sweep took 41 minutes

On 30 July someone worked through 1,196 bitcoin addresses and emptied them, taking 1,082.65 bitcoin, worth roughly 70.2 million dollars, in a window of 41 minutes. Nobody picked a lock. No device was touched, no user was phished, no server was breached. The attacker did not need any of that, because the private keys protecting those addresses could be worked out from scratch. The first reports put the loss near 38 million dollars; as researchers finished counting, the figure landed at nearly double that.

The devices involved were Coldcard hardware wallets made by Coinkite, the product category people buy specifically to keep keys away from networks. That is what makes the incident worth an hour of any operator's attention, whatever they think of bitcoin. The failure did not happen at the perimeter that everyone budgets for. It happened at the moment the secret was created, years before anyone tried to steal it.

A macro set to zero switched on the fallback

Coinkite's own technical account is unusually candid about the mechanism. In March 2021, during a migration to Bitcoin Core's libsecp256k1, wallet seed generation was redirected from the routine that called the device's hardware random number generator to a general-purpose one. That new path resolved to MicroPython's software fallback rather than Coldcard's hardware implementation. The fallback code itself had existed since May 2018 and had never touched seed generation until that migration.

The reason it compiled at all is the part worth copying into your own review checklist. The guard around the fallback tested whether a configuration macro was defined, not whether it was set to one. The developers had set that macro to zero, meaning the hardware generator was not needed there, and a macro set to zero is still a macro that is defined. The guard read the presence of the value rather than the value itself, and switched the fallback on. Nobody wrote weak cryptography. The hardware generator existed and worked. It simply stopped being what the seed was drawn from.

Five years passed and every test still passed

On Mk2 and Mk3 devices running firmware 4.0.1 through 4.1.9, the resulting seeds carried about 40 bits of entropy instead of the 128 a twelve-word phrase is supposed to have. On Mk4, Mk5 and Q the picture was better but not safe: engineers had mixed values from the secure elements into the generator state as, in Coinkite's phrase, a backup to a backup, which lifted those seeds to roughly 72 bits. Both numbers are catastrophic in the same way. Randomness is not something you can see. A key with 40 bits behind it signs transactions, verifies addresses and restores from backup exactly like a key with 128, so every functional test the company and its customers ran for five years passed, correctly, while the product was broken.

Coinkite also volunteers a detail that most vendors would have buried. A few weeks ago, it writes, the company used one of the best available AI models to review its code for security issues, and it did not find this bug. That is worth sitting with before the next vendor tells you their code has been reviewed by a model. The defect was not subtle in hindsight and it was not hidden, but it lived in the gap between a build configuration and a cryptographic assumption, which is precisely the seam that a reviewer reading for code quality is least likely to treat as a security boundary.

The fix protects the next key, not the last one

Coinkite shipped corrected firmware on 31 July for every affected model and release track: 4.2.0 for Mk2 and Mk3, 5.6.0 for Mk4 and Mk5, 1.5.0Q for Q, and the corresponding edge builds. Then it published the sentence that matters more than the patch. Updating the firmware does not change or repair an existing seed. The company's instruction is to install the fixed firmware, generate a new seed on the updated device, record and verify its backup before depositing anything, confirm a new receiving address on the device screen, send a small test transaction, and only then move the remaining funds.

That is a migration, not an update, and the distinction is the whole lesson. Two things could save a wallet created in the affected window: fifty independent private dice rolls entered through the device's own dice feature, since Coldcard hashed those into the seed, or a strong unique passphrase, which sits as a separate barrier in front of the weak seed. Coinkite still tells even passphrase-protected users to migrate as soon as practical. TAPSIGNER, OPENDIME and SATSCARD run different codebases and are unaffected.

Inventory what you generated, not just what you run

Almost every patch process an owner has ever signed off treats software version as the unit of risk. You learn a version is vulnerable, you upgrade it, the exposure ends. Entropy defects break that model completely, because the damage is not in the running code but in artefacts the code emitted and handed to you: keys, tokens, session identifiers, recovery codes, API secrets, certificates. Those objects outlive the version that made them, travel into backups and third-party systems, and carry the weakness with them permanently. Upgrading the generator ends the production of bad secrets. It does nothing about the inventory.

So the question to put to any vendor whose product creates secrets on your behalf is not only which versions are affected. It is which secrets were generated on an affected version, how you enumerate them, and what the rotation path is. That applies well beyond hardware wallets, to the HSM in the payments stack, the certificate authority, the device provisioning line, the identity provider issuing long-lived tokens. Anywhere a machine mints something you later rely on, the defective window is the thing to inventory, and almost nobody keeps a record of it.