CLOSED NETWORK
no trackers

The Coldcard Exploit: When the Random Number Generator Wasn't Random

A single line of C code asked the wrong question, and for five years Coldcard hardware wallets generated bitcoin seeds a laptop could guess. More than $130M is gone. What happened, who's affected, and what to do tonight.

There is a particular kind of person who bought a Coldcard.

They didn't leave their bitcoin on an exchange. They didn't trust a custodian. They read the arguments, took the harder path, bought a hardware wallet from a company with a reputation for being uncompromising about security, and wrote twenty-four words onto a piece of metal that went somewhere safe.

On the morning of July 30th, in a forty-one minute window, more than a thousand of those wallets were emptied.

Nobody touched a device. Nobody phished anyone. Nobody found a metal backup.

The attacker just guessed the words.

As I write this on August 4th, the running total is somewhere north of two thousand bitcoin — roughly $130 million — across more than 7,700 addresses, and it is still climbing. This is not a story about people who were careless. It's a story about what happens when a chain of very good decisions terminates in one line of code that asked the wrong question.

I want to walk through the technical failure properly, because it's one of the cleanest security lessons I've seen in years. Then I want to tell you exactly what to do if you're affected. And then I want to talk about the part of this story that belongs on a privacy podcast specifically — which isn't the money at all.

First, what a seed phrase actually is

Everything hangs off this, so bear with me for ninety seconds.

Your bitcoin wallet is not really a wallet. It's a number. One enormous secret number, and everything else — your addresses, your keys, that list of twenty-four words — is derived from it. If someone else can produce that number, they own your coins. There is no password reset. There is no fraud department.

So the entire security of the arrangement rests on one question: how random is that number?

The standard is 128 bits. And I want to give you a feel for that, because "128 bits" reads like a spec on a box. A 128-bit secret has roughly 3.4 × 10³⁸ possible values — about 340 undecillion. Here's the scale: the entire global bitcoin mining network, running flat out at its current hashrate, would need something close to the present age of the universe to grind through them all. That isn't a marketing claim, it's arithmetic.

Now hold that, because here's the other end of the scale. Forty bits is about a trillion possibilities. A trillion sounds like a lot.

A trillion is a laptop and a weekend.

That gap is the entire story.

Bar chart comparing intended 128-bit entropy against the ~72, ~32 and ~40 bits Coldcard devices actually produced

Bar length tracks bits, not guesses. Each bit doubles the work — which is why the visual gap looks survivable and the real one isn't.

The bug

A Coldcard has a genuine hardware random number generator on its chip — physical silicon producing real unpredictability. That's a meaningful part of what you're paying for.

Coinkite wrote their own code to talk to that hardware. And because they'd written their own wrapper, they told the underlying operating system — a build of MicroPython — to turn its built-in random number generator off. They set a configuration flag, MICROPY_HW_ENABLE_RNG, to zero. Off. We've got this.

Then, in a separate library called libngu, there was a compile-time check. That check was supposed to ask: is the hardware generator enabled?

What it actually asked, via #ifndef, was: does that setting exist?

It existed. It was set to zero — but it existed. The guard passed. The code bound itself to MicroPython's software fallback generator instead.

No error. No warning. It compiled clean.

That fallback is a small, fast, deterministic algorithm called Yasmarang. It's not a cryptographic generator and was never meant to secure anything. And what did it seed itself from? Three values: the microcontroller's unique hardware ID — fixed for the life of the chip and readable straight out of memory — plus a SysTick timer reading and a real-time-clock value.

So the randomness protecting these wallets was, in practice: a serial number an attacker can look up, plus what time it was when you pressed the button.

That went into production in March 2021, in the v4.0 firmware — Block dates the regression to 4.0.0 on March 17th, and 4.0.1 is the first publicly listed release on the affected range. It sat there for five years and four months.

How bad, by model

On Mk2 and Mk3, you get roughly forty bits. Block's engineering team, who published the technical teardown, put it more starkly than that: once the device UID and timer state are known, seed generation on those models is effectively deterministic. Not merely guessable. Reproducible.

On Mk4, Mk5 and Q, there's a partial rescue. From March 2022, Coinkite began mixing in entropy from the device's secure element — which is where the widely quoted "72 bits" comes from. But Block found the mixing was broken too. The firmware hashes that secure-element entropy and then retains only four bytes before reseeding. Four bytes. Thirty-two bits. It doesn't accept the full digest, doesn't initialize a proper cryptographic DRBG, doesn't reset the rest of the generator's state.

And hashing cannot manufacture randomness that isn't in the input. Whatever you do to 2^32 possibilities downstream, you still have 2^32 possibilities. The real search space on a modern Coldcard was about two billion candidates on average.

Two billion, for a nine-figure prize. That's not a supercomputer problem. That's a cloud bill.

Why it needed nothing from you

The attack requires no physical access, no malware, no supply chain interference, no mistake on the owner's part. You generate candidate seeds, derive the addresses, and query the public blockchain to see which ones hold money.

The blockchain being public — normally the feature that makes bitcoin auditable — is what let attackers find the funded wallets instantly.

Diagram of the Coldcard firmware bug: a preprocessor guard checks whether MICROPY_HW_ENABLE_RNG exists rather than what it is set to, silently binding to a deterministic software PRNG

The whole failure in one picture: a guard that asked whether a setting existed instead of what it was set to.

What it has cost

Disclosure landed July 30th. Between 01:10:20 and 01:51:26 UTC, 1,082.65 BTC — about $70.2 million — left 1,196 addresses in forty-one minutes. Inside that window sits a twenty-five minute stretch in which the attacker cleared 594 BTC, roughly $38 million, out of about five hundred single-signature wallets. They went for the largest balances first. (A lot of coverage presents that 594 BTC as a separate second wave — it isn't, and reporting it that way double-counts.)

A genuine second wave followed, adding around 76 BTC across nearly 1,500 more addresses, bringing the cumulative total to 1,158.81 BTC from 2,673 addresses. A third took 208 BTC from 1,912 addresses over the weekend.

By Monday the 3rd, Fortune reported 1,816 BTC and $116 million across more than 5,200 addresses. By Tuesday, Galaxy Research was tracking over 2,000 BTC — around $130 million — across 7,700+ addresses. (Addresses, not wallets. One wallet can hold many.)

And the shape of the thing has changed. Alex Thorn at Galaxy: "now NUMEROUS different attackers exploiting the Coldcard vulnerability. we estimate at least 15 different attackers now."

It's no longer one sophisticated actor. The method is public and understood, and it has become a race.

One more figure, and it's the one that stayed with me: the coins being taken had been dormant for an average of 3.18 years.

That's not traders. That's people who bought a hardware wallet, moved their savings into it, wrote down the words, and stopped looking — because that is precisely what everyone in my line of work told them to do.

What to do

If you own a Coldcard, or know someone who does, here is the practical picture. I'd genuinely encourage you to pick up the phone about this one.

Are you affected?

It is the firmware that was running when the seed was created that matters — not what's installed today. If you generated a seed on a Coldcard and later restored it into a different wallet or another brand of device, that seed is still affected.

At risk:

  • Mk2 / Mk3 on firmware 4.0.1–4.1.9
  • Mk4 on 5.0.0–5.5.x
  • Mk5 on anything through 5.5.x
  • Q on anything through 1.4.x
  • On the Edge track: Mk4/Mk5 below 6.6.0X, Q below 6.6.0QX — and Coinkite warns specifically that a higher-numbered Edge 6.x should not be assumed fixed. That's a real trap.

Not affected:

  • Original Mk1 (can't run the affected firmware)
  • Mk2 / Mk3 on 3.2.2 or earlier
  • Seeds generated from 50+ fair, independent, private dice rolls — the one exemption Coinkite stands behind
  • Seeds never generated on a Coldcard
  • Tapsigner, Opendime and Satscard

A strong, unique BIP-39 passphrase adds real protection. Coinkite's wording is careful, though: a short, common, patterned, quoted or reused passphrase may still be guessable, and they recommend migrating regardless. I'd take that advice.

If you can't remember what firmware you were on in 2021 — assume you're affected. Migrating unnecessarily costs you an afternoon.

Update, then migrate — and understand the difference

Fixed firmware shipped on July 31st: 4.2.0+ for Mk2/Mk3, 5.6.0+ for Mk4/Mk5, 1.5.0Q+ for the Q (Edge track: 6.6.0X and 6.6.0QX).

Coinkite is blunt about the limit: "Updating the firmware does not change or repair an existing seed." It fixes what the device makes from now on. Your existing key was derived from bad randomness, and that can't be undone.

So the order of operations, and don't skip steps because you're panicking:

  1. Install the fixed firmware for your exact model and track.
  2. Generate a completely new seed on the corrected device.
  3. Back it up, verify the backup, check the fingerprint.
  4. Confirm a receive address on the device screen itself.
  5. Send a small test transaction and let it confirm.
  6. Only then move the remaining balance.
  7. Keep the old backup until migration is complete.

Coinkite specifically warns that rushing a migration can create a more immediate risk than the one you're escaping. Self-inflicted losses during a panic move are a real category. Go carefully.

If you don't have a good long-term destination ready today, temporarily parking funds at an exchange you trust is a legitimate stopgap. It costs you privacy — a real cost, and I won't pretend otherwise — but it beats losing the coins. Make it a deliberate choice rather than a default.

Rotate everything else that device generated

This is the part most coverage is missing, and it matters even if your seed came from dice.

The same broken generator fed every feature on the device that needed randomness:

  • New and ephemeral wallet seeds
  • Paper wallet and raw private keys — directly usable secp256k1 keys
  • Seed XOR masks
  • Ephemeral ECDH keys for cloning, USB encryption and Key Teleport (the multisig-PSBT variant of Key Teleport is only weakly affected, since its keys derive from the existing wallet)
  • TOTP shared secrets for Web2FA
  • Password generator output, including Secure Notes passwords
  • HSM local-code material

Dice rolls protected your seed. They protected nothing else. If you ever generated a password or a paper wallet on an affected Coldcard, rotate it.

If you use multisig

One question: can any single spending path be satisfied by affected Coldcards alone?

If two of your three signers are affected Coldcards in a 2-of-3, you are in the same position as a single-sig user. Move with the same urgency, and don't talk yourself out of it on a technicality.

If your quorum requires a device from a different manufacturer running different firmware, you're in much better shape — a single vendor's entropy bug cannot reach your threshold.

That last point is the durable lesson here, and I'll come back to it.

And a few don'ts

Don't rely on a firmware update alone. Don't attempt to white-hat sweep wallets that aren't yours — the attribution and legal problems are worse than they look. Don't reuse a compromised seed on any device for any amount. And don't assume small balances are beneath notice; attackers are enumerating candidates and checking every derived address.

Above all: there is now a public, confirmed population of hardware wallet owners in distress, and the phishing wave that follows is entirely predictable. Every unsolicited "recovery service," urgent email, DM and phone call about this is hostile until proven otherwise. Coinkite will never ask for your seed phrase. Nobody legitimate ever will.

The two uncomfortable parts

Two things worth sitting with once the immediate work is done.

The AI story

Coinkite's explanation for how this was found is worth quoting exactly, because the phrasing matters: they "have to assume that someone used AI to review previous versions of our firmware and stumbled upon this issue." They added a detail I found genuinely unsettling — they had run "one of the best available AI models" over the same code themselves, weeks earlier, and it "did not find this bug or anything serious."

Note what that first sentence is. It's an assumption, not a finding. Nobody has produced evidence of how the original attacker actually located the flaw. And plenty of researchers pushed back, with a fair objection — this bug class is well documented in embedded systems literature and a careful human reviewer could absolutely have caught it. "AI found it" is a comfortable story for a company that shipped a five-year flaw in open source.

But strip out the excuse and there's a real signal underneath. NVK, Coldcard's co-founder, argued that AI-assisted code review can now surface latent bugs faster than expert humans can. Directionally I think that's true, and if it is, then every piece of open source security software written before this year now sits in a different threat environment than the one it was audited in.

The code didn't change. The cost of finding what's wrong with it did.

The part that belongs on this site

To warn people, Coinkite emailed its customers. That was the right call — and it required having those email addresses. Addresses going back to 2019.

From a company whose CEO had publicly said customer data was erased within ninety days of purchase, and which sells anonymous purchasing as a feature.

Their explanation is that purchase emails are retained so customers can log in and verify their other details were blanked. They also acknowledged there's no deletion schedule for them. The addresses will be kept, in their words, "for now."

I don't think that's villainy. I think it's the most ordinary thing in the world — a retention policy that was true in spirit and never quite true in the database. Nobody sat down and decided to lie. Somebody built a login system, and the emails stayed because deleting them would have broken it, and the marketing copy was written by someone else in a different year.

But it's worth naming plainly, because it's the pattern we hit on this site constantly: the data you were told was deleted is usually still there. It surfaces at the moment it becomes useful.

This time, the moment it became useful was a security warning that may have saved people their savings. That's a genuinely good outcome, and I'd rather Coinkite had those emails than not.

You just don't get to choose which moment it is. Sometimes it's an urgent warning. Sometimes it's a subpoena, a breach dump, or an acquisition where the customer list is an asset on the balance sheet. The retention is the same either way. Only the trigger differs.

What I'd take from this

The reflex reaction is "see, self-custody is too dangerous, just use an exchange." I'd resist that hard. An exchange failure takes everyone at once and there's no version of it where you had any control at all.

What this actually is, is a lesson about where trust concentrates.

Every one of those thousands of people made a good decision. They bought a well-regarded device from a company that has been more transparent than most, and has behaved reasonably well in the crisis — fast disclosure, fixed firmware inside a day, direct warnings to customers. They still lost, because all that good judgment funnelled into a single point of failure: one company's firmware, one build flag, one guard that checked whether a setting existed instead of what it said.

The answer isn't more trust in a better vendor. It's redundancy across vendors. Multi-vendor multisig. Your own dice. Anything that means no single organization's mistake can reach your threshold on its own. That stopped being a theoretical nicety this week and became the thing that separated the people who lost everything from the people who didn't.

And the meta-lesson, which I'll be repeating for a while: open source is necessary, but it is not sufficient. This code was public the entire time. Anyone could read it. For five years and four months, apparently nobody with the right eyes did — until someone with a machine did, and they weren't on our side.

"Many eyes make all bugs shallow" was always a claim about attention, not about licensing. Attention is the scarce thing. It always was.

If you own one of these, go and check tonight. Not this weekend.

And call the friend you talked into buying one.

— Simon


Sources & further reading

// Encrypted Dispatches

Become A
Smaller Target.

One email per week. Real privacy news, working tools, no fearmongering. We don't sell your address. We don't even want your real email address.

Subscribe
5,000+ readers · unsubscribe in one click · consider supporting the show