
13 min read
The Coldcard Hack Explained: RNG Flaw, Affected Firmware & Migration
Nobody touched a device.
No phishing email. No malicious app. No stolen laptop, no compromised backup, no seed phrase typed into a fake support page. The people who lost bitcoin in the Coldcard hack on 31 July were doing everything right by the standard advice: keys generated offline, on dedicated hardware, on a device with a reputation built specifically on not trusting anything else.
Between 01:31 and 01:56 UTC, CoinDesk timed the first sweep at 594 BTC drained from around 500 wallets across 1,324 transactions and a three block window. Twenty five minutes. More waves followed over the days after.
One thing about it changes what you should do next: the attackers never needed access to anyone's Coldcard. They worked out the seed phrases from scratch.
What actually broke in the Coldcard hack
Start with what a seed phrase is, because the whole story sits on this one fact.
Your twelve or twenty four words are not a password. They are a very large number, written in a format humans can copy down without making mistakes. The number is what protects you. And the only thing making that number safe is that it was picked unpredictably from a pool so enormous that nobody can search it.
That pool gets measured in bits. Each extra bit doubles it. A properly generated seed carries 128 bits of unpredictability, which works out to roughly 340 undecillion possibilities, a 3 followed by 38 digits. No machine that exists or is on any engineering roadmap can work through a pool that size. That is the whole basis on which self-custody is safe.
So a hardware wallet's most important job happens in the first few seconds of its life, before you have signed anything: it has to generate a genuinely unpredictable number. Coldcard has dedicated hardware for exactly this, a true random number generator that pulls from physical noise.
For five years, on affected firmware, that hardware was never asked.
How a build flag turned a hardware wallet into a predictable one
The cause is small enough to fit in a sentence, which is what makes it worth understanding.
Coldcard's code defined a setting called MICROPY_HW_ENABLE_RNG and set it to zero, because they were using their own hardware generator instead of the one built into MicroPython. A supporting cryptographic library, brought in during a 2021 migration, checked whether that setting existed rather than whether it was switched on. It existed. Its value was zero. The check passed, the safety error that should have stopped the build never fired, and the code quietly fell through to MicroPython's software fallback.
In Coinkite's own words: "The guard used #ifndef, which tests whether MICROPY_HW_ENABLE_RNG is defined, rather than whether its value is nonzero. We defined that macro as zero, so the #error did not stop the build."
The software fallback was not random. Block's analysis shows it was started from the chip's hardware ID combined with a timer value, then topped up from the real-time clock registers, and those values were read once and never refreshed. Coinkite describes the same thing as seeding "primarily from device and timing state." None of it is secret. Feed a generator like that the same starting value and it produces the same output every time, reliably, by design.
So the pool shrank. On Mk2 and Mk3 devices it collapsed to roughly 40 bits, which is about 1.1 trillion possibilities. A trillion sounds enormous and is not: a decent laptop can work through it, and a GPU cluster can do it in hours.
Mk4, Mk5 and Q mix in extra entropy from their secure elements, and this is where the two published analyses diverge. Coinkite estimates the effective search space on those models at about 72 bits. Block found that the reseed pulls only four bytes from the secure element, replacing a single word of the generator's internal state and leaving the rest untouched, which by its reckoning leaves "at most 2^32 securely distinguished output streams." Block is careful to say it has not done full empirical testing to confirm exploitability and points readers to Coinkite's definitive report once it exists.
Treat that disagreement as a live one. If you hold an Mk4, Mk5 or Q, the safer assumption is the more pessimistic one.
From there the attack is mechanical. Generate the candidate seeds, derive the bitcoin addresses each one would produce, check those addresses against the public blockchain, and sweep whatever holds a balance. The blockchain is public, so no part of this requires touching a wallet, a network connection, or a person.
Nothing on the screen could have told you
Here is the detail that should stay with you longer than the firmware version numbers.
A weak random number generator does not produce output that looks weak. The words on your Coldcard's screen during setup looked exactly like a properly generated seed, because they were properly formatted, correctly checksummed and statistically unremarkable. Output from a predictable generator passes randomness tests comfortably. It looks random. It was simply decided in advance by a starting value anyone could reconstruct.
You could not have caught this by being careful. You could not have caught it by checking your backup, verifying your address, or testing a small transaction first. Every one of those checks would have passed.
The flaw was found by Block's bitcoin engineering and security teams, who traced it through firmware analysis and disclosed it to Coinkite before publishing. It had been shipping since firmware 4.0.1 in March 2021.
Who the Coldcard hack affects, exactly
This matters more than the headline number, because the bug only reaches seeds that were generated by affected firmware. Per Coinkite's advisory:
Affected, migrate the seed:
- Mk2 and Mk3 on firmware 4.0.1 through 4.1.9. Roughly 40 bits. Treat this as urgent.
- Mk4 and Mk5 below 5.6.0. Roughly 72 bits.
- Q below 1.5.0Q. Roughly 72 bits.
Not affected by this bug:
- TAPSIGNER, OPENDIME and SATSCARD, which run different codebases.
- Mk1. Coinkite's advisory doesn't list it either way, but Block's analysis found that Mk1 through v3.2.2 uses the STM32 hardware generator directly, and that the regression only entered with v4.0.0.
- Seeds created with at least 50 fair, independent, private dice rolls. Coinkite says these are not at risk "from this RNG issue alone", and asks you to read its separate guidance before migrating rather than assuming you're clear.
Seeds generated on another device and imported to a Coldcard should also be outside this, since the bug sits in generation rather than in storage or signing. Coinkite's advisory doesn't address imported seeds directly, so that's the mechanics rather than an official all-clear.
Updating firmware does not repair a seed that already exists. The weak number was created once, years ago in many cases, and it is still the number protecting your coins. The patch stops new seeds being made badly. It cannot reach back.
What to do if you hold a Coldcard
Coinkite's guidance, in order:
- Update to the fixed firmware from the official source before generating anything. Mk2 and Mk3: 4.2.0 or later. Mk4 and Mk5 Standard: 5.6.0 or later. Q Standard: 1.5.0Q or later. Edge builds: 6.6.0X, and 6.6.0QX for Q.
- Generate a completely new seed on the updated device. On Mk4, Mk5 and Q the fixed firmware's own seed generation is sufficient and dice rolls are optional.
- Record and verify the new backup, the wallet fingerprint, and a receive address. If you set a passphrase, store it separately from the seed words.
- Send a small test transaction before moving the remaining funds.
- Keep the old backup until the migration is complete and confirmed.
That last step is worth reading twice. The instinct after an incident like this is to destroy the old backup immediately, and that instinct will lose you money if anything goes wrong mid-migration. The old seed is compromised, but until your funds are confirmed in the new wallet it is still the only thing that can reach them. Retire it after, not during.
If you are on an Mk3 with a seed made any time since 2021, do steps one and two today rather than this weekend. Forty bits is genuinely low.
One note on the numbers you have seen reported. Galaxy Research counted 1,596 BTC taken across roughly 7,300 addresses as of 4 August. TRM Labs published a figure of about 1,816 BTC, or $116 million, across more than 5,200 addresses. Both called their figures preliminary, funds were still moving when each was written, and Coinkite has not published a loss estimate of its own. Expect the total to keep moving. The firmware guidance above is not in dispute.
The part of self-custody nobody can inspect
Most security advice for holders covers things you can observe. Check the address before you send. Verify the domain. Don't type your seed into anything. Buy from the manufacturer, not a marketplace. All of that is good advice, and all of it is about catching a mistake as it happens.
Key generation is different. It happens once, it produces no evidence about its own quality, and by the time it is wrong there is no signal anywhere in the system telling you so. Your wallet works. Your transactions confirm. Your backup restores correctly. The failure is completely silent until it isn't.
That is the real lesson here, and it applies well beyond one manufacturer. Any wallet, hardware or software, is making a promise about randomness that you have no way to audit yourself. You are trusting a build process you will never see.
Which points at the thing that actually reduces the damage when that trust turns out to be misplaced: how much a single secret is worth on its own.
Every person who lost bitcoin in this incident lost all of it in one transaction. Not because the attacker was sophisticated, but because one number was the entire security model. Guess the number, own the wallet. There was no second step to get past.
What changes when no single secret is the whole wallet
CoinWallet supports multi-party computation, or MPC. Rather than one seed phrase sitting behind everything, the signing ability is split into separate pieces held in different places, and a set number of them have to come together before a transaction can be approved.
No single piece can move your crypto. It takes the required pieces, working together, to approve any transaction. One key, one device, one stolen piece is never enough.
In practice that means you can create an MPC wallet and co-manage assets with other people, join one through an invitation code, import an existing key shard, and replace a lost device through a threshold-gated process rather than a single recovery phrase that unlocks everything.
Now the honest part, because this incident deserves it: MPC does not repeal the randomness requirement. Key shards are generated too, and generation quality still matters. What splitting does is remove the single guessable secret. An attacker who works out one piece has one piece, and one piece does not sign. The failure has to happen in more than one place before you lose anything, which is a meaningfully harder thing to arrange than a single weak number.
Multisig on bitcoin gets you a similar property by a different route: several independent keys, a required number of signatures, and no single phrase that hands over everything.
The advice hasn't changed, exactly. It has just moved. For years the message to holders was to get your keys away from exchanges and onto your own hardware, and that message was right. This incident adds the next line: getting the keys onto your own hardware is worth doing, and it is not the same thing as being safe, because you have simply moved your trust from a company that could be hacked to a build process nobody outside the manufacturer had read in five years.

