Coldcard's firmware checked if a setting existed, not if it was on. $88.6 million in Bitcoin is gone.
A 2021 build error routed Coldcard seed generation to a software PRNG. Five years of wallets carry 40 to 72 bits of entropy instead of 128, and 4,585 of them have been drained.
Coldcard shipped a build flag that silently disabled its own hardware random number generator. For five years, every seed phrase the device generated came out of a software PRNG seeded from a chip ID and a timer. On July 30, someone drained 1,196 of those wallets in 41 minutes.
Coinkite, the Toronto company behind Coldcard, has now published patched firmware and a technical post-mortem. Neither one fixes an existing seed. Anybody who generated a wallet on an affected device has to move the coins to a new wallet, created fresh on the patched build. Galaxy Research counts 1,367 BTC gone from 4,585 addresses, roughly $88.6 million. The bug that allowed it is a single preprocessor directive that compiled without a warning.
What the build actually did
The story starts in March 2021, during a migration to Bitcoin Core’s libsecp256k1 library. Coldcard’s firmware wanted its own STM32 TRNG for seed generation. It got MicroPython’s fallback instead, and the reason is small enough to fit in a tweet.
The guard read #ifndef MICROPY_HW_ENABLE_RNG, which tests whether a macro exists. Coinkite had defined that macro as zero. Existence check passes, #error never fires, build proceeds. Two separate implementations of rng_get() were in scope with identical signatures, so the linker resolved the call to MicroPython’s Yasmarang PRNG and reported nothing unusual. The correct hardware routine was compiled into the binary the whole time. Nothing ever called it.
Coinkite’s own technical backgrounder names the gap in its process directly: the build “did not verify end-to-end symbol resolution and call reachability from wallet seed generation.” That’s the whole failure in one clause. Unit tests confirmed the right function produced good randomness. Nobody tested which function the seed path reached.
Yasmarang is not a cryptographic generator and was never meant to be one. On Mk2 and Mk3 hardware it was seeded, in Coinkite’s words, “primarily from device and timing state”: the chip’s unique ID and some timer registers. Both are values an attacker can model. A unique ID is a fixed constant per device drawn from a narrow manufacturer range, and boot timing lands in a predictable window.
Why 72 bits still isn’t safe
A 12-word BIP-39 phrase is supposed to encode 128 bits of entropy. The practical meaning of that number is that no adversary will ever enumerate the space.
Coinkite’s estimates for affected devices:
- Mk2 and Mk3: roughly 40 bits of effective search space. That’s a weekend on rented hardware.
- Mk4, Mk5 and Q: roughly 72 bits, because those models mixed values from the SE1 and SE2 secure elements into the PRNG state as, again quoting Coinkite, “a backup to a backup.”
Seventy-two bits is the number worth sitting with. It sounds large. It is 56 bits short of the design target, which means the search is about 72 quadrillion times cheaper than it should be. Grinding 2^72 candidates is not a laptop job, but the attacker here didn’t need the full space. Seeds share structure: a limited ID range, a narrow boot-timing window, a known PRNG. Every one of those constraints cuts the exponent again.
The 40-bit case needs no cleverness at all. A trillion candidates is a rounding error for a single GPU, and every Mk2 or Mk3 seed made between the 2021 build and the fix sits inside that space. Those are also the oldest devices in the fleet, which means the wallets most likely to hold years of accumulated coins are the ones with the weakest keys. That inversion is why the loss figure is as high as it is relative to the address count: the average drained address held about 0.3 BTC.
One escape hatch exists. Coinkite excludes any seed generated with at least 50 independent, private dice rolls, because user-supplied entropy swamps whatever the broken generator contributed. If you did the dice ceremony, you’re fine. Most people didn’t.
How the coins left in 41 minutes
The drain came before the disclosure, which is the detail that makes this a theft story rather than a patch story.
On July 30, an attacker emptied 1,196 addresses in 41 minutes, taking 1,082.65 BTC worth about $70.2 million at the time, according to The Hacker News. Galaxy Research then identified two further waves, pushing the total to 1,367.05 BTC across 4,585 addresses, near $88.6 million. Chainalysis analyzed the targeting pattern. Coinkite shipped fixed firmware on July 31 at 9:33 a.m. EDT, about a day after the first transactions went public, and admitted in the advisory that “we were unaware of the bug until today.”
Nobody has published a forensic chain proving the RNG flaw is how the keys were derived. The link rests on address clustering and on the affected-device profile matching the drained set. Treat it as a strong inference from two research firms, not a confirmed root cause.
That ordering has a practical consequence for owners. In a normal disclosure the vendor patches, then researchers publish, then attackers start work, and users get a head start measured in weeks. Here the head start went the other way. Whoever holds the derivation method has had the full address space since before July 30, and the 4,585 emptied addresses are the ones that happened to be worth the transaction fees. Every affected wallet still holding coins today is queued behind them. Coinkite’s advisory language reflects that urgency, telling owners to stop creating new wallets until they have updated and to move funds rather than wait for further guidance.
How the attacker found the bug is also unsettled, and the theory circulating is that a model read the code. Coldcard co-founder NVK wrote that “AI-assisted code review can now find latent bugs at a speed that is outpacing even the industry’s most seasoned experts.” He offered that as a warning to other firmware teams rather than as evidence about this attacker. Bitcoin developers on r/Bitcoin reproduced the discovery after the fact, reporting that Claude Code surfaced the guard after eight minutes on a prompt that just asked it to check for vulnerabilities. That thread cleared 1,700 upvotes in a day.
Competitors moved fast to distance themselves. BitBox published a point-by-point analysis of its own entropy path within hours. Reasonable, and also a reminder that “we use a hardware TRNG” is a claim about intent, not about what the linker did.
What this means for you
If you own a Coldcard, a firmware update on its own does nothing for you. The order of operations matters. Verify your existing backup first. Install the fixed build for your model: 4.2.0 or later on Mk2 and Mk3, 5.6.0 or later on Mk4 and Mk5, 1.5.0Q or later on Q, or the 6.6.0X and 6.6.0QX Edge releases. Generate a completely new seed on the patched device. Send a test transaction, confirm it lands, then migrate the rest and keep the old backup offline. Coins sitting on an old seed are exposed until they move.
For everyone else, the transferable lesson is about what your tests actually cover. A unit test that calls the right function proves the right function works. It proves nothing about which symbol the production call site resolves to, and a silent fallback with a matching signature is the ideal shape for that gap to hide in. Coinkite’s patch now excludes MicroPython’s fallback object outright and adds a build-time symbol check, which is the assertion that should have existed in 2021.
We have already seen a Hanwha camera ship a live GitHub admin token in its login page and Flipper Zero’s firmware future turn on a 700 KB flash ceiling. Embedded builds fail quietly, and quiet failures are the ones that survive five years. The other thing to watch is the review asymmetry: models found a lattice weakness in HAWK in about 60 hours of cryptanalysis, and the same speed advantage applies to any open-source wallet firmware sitting on GitHub. My read: if you ship security-critical embedded code, assume an adversary has already run it through a model this quarter, and go audit your own build flags before they do.
Share this article
Quick reference
Sources
- Coldcard Security Advisory — Coinkite
- Technical Deep Dive into the Entropy Issue — Coinkite
- COLDCARD wallet RNG flaw likely linked to $88 million Bitcoin theft — BleepingComputer
- Coldcard Hardware Wallet Flaw Linked to $70 Million Bitcoin Theft in 41 Minutes — The Hacker News
- Coinkite Releases Fixed Firmware After Coldcard Bug; AI Likely Involved In The Breach — Bitcoin Magazine
- BitBox is not affected by the Coldcard RNG vulnerability — BitBox
Frequently Asked
- Is my Coldcard affected?
- If the seed was generated on a Mk2 or Mk3 running firmware 4.0.1 to 4.1.9, a Mk4 or Mk5 before 5.6.0, or a Q before 1.5.0Q, yes. Seeds imported from elsewhere are unaffected.
- Does updating the firmware fix my wallet?
- No. Coinkite is explicit that installing the patch does not repair a seed already generated. You need a new seed created on patched firmware, then a migration.
- What if I rolled dice when I set the device up?
- Coinkite excludes seeds built with at least 50 independent private dice rolls. Your own entropy dominated the flawed generator in that path.
- Are other hardware wallets exposed to the same bug?
- This was a Coldcard build error, not a shared library flaw. BitBox published its own analysis confirming its devices use a different entropy path.