cAPSLOCK tagged me about the Coldcard thing. I dug through the technicals here's the full picture for anyone who wants more than the headline.
Timeline of the bug
March 2021: Coinkite merged commit b18723dd. They migrated wallet seed generation from ckcc.rng_bytes() (direct STM32 hardware TRNG) to ngu.random.bytes() (their libNgU wrapper around MicroPython). The goal was to standardize on Bitcoin Core's libsecp256k1. The intention was fine. The integration was not.
Here's the specific code failure: libNgU's guard uses #ifndef MICROPY_HW_ENABLE_RNG it checks whether the macro is defined at all, not whether its value is non-zero. Coldcard's board config defines MICROPY_HW_ENABLE_RNG as (0) because they provide their own hardware RNG wrapper. So the guard passes, but the actual rng_get() resolves to MicroPython's Yasmarang fallback instead of the STM32 hardware TRNG.
Yasmarang is a deterministic PRNG from 2001. Four words of state: pad, n, d, dat. Seeded from the MCU UID (fixed factory serial), SysTick counter, and RTC registers. None of those are secrets.
For Mk3 users: that's it. No cryptographic entropy added at all. Coinkite estimates the effective search space at ~40 bits. That's brute-forceable if you can constrain the timing window.
For Mk4/Q/Mk5: slightly better but not safe. They added a boot-time reseed from the secure elements. Problem: only 4 bytes (32 bits) of the hash survive. The reseed function replaces exactly one word of the Yasmarang state. Block.xyz's analysis puts the ceiling at 2^32 distinct output streams.
The exploit
Between 01:31 and 01:56 UTC on July 30: 594 BTC (~$38M) drained from ~500 single-signature addresses. 1,324 chunks across 500 transactions inside a 3-block window. 562 BTC consolidated into bc1qq85v2c926eg6pgxhwp6q7lf6cnsz80qs3fcu9r hasn't moved since.
Every drained address held >0.15 BTC. Many dormant for years. The coin age matches the bug window almost exactly 2021 to 2026.
The attacker didn't need to compromise devices. They narrowed UID ranges (STM32 UIDs are sequential and partially guessable from manufacture date), constrained timing windows, brute-forced seeds offline. A single on-chain public key from any of those addresses served as their validation oracle.
Dice rolls save you
If you entered 50+ fair, private dice rolls during seed creation: the advisory says you're fine from this RNG issue, because those rolls get independently hashed into the result. Fewer than 50 or unclear: migrate.
Passphrases help proportionally to their strength. A strong, unique BIP-39 passphrase adds an independent barrier. A weak one you used for four other wallets doesn't.
What I'd do if I had a Coldcard-generated seed from 2021 onward
Don't wait. Don't check whether your addresses appear in the compromised list the attacker may not have gotten to yours yet. Upgrade firmware to 5.6.0 (Mk4/Mk5) or 1.5.0Q (Q1), generate a new seed, migrate. Send a test transaction first. Verify the new receive address on the device screen.
The broader lesson
Hardware wallets are hardware wallets they isolate the private key from your internet-connected machine. They don't automatically guarantee that the random number generator is doing what you think it's doing. This is the kind of bug that external audit, FIPS validation, and AI-assisted code review all missed. The code was open source the whole time, which is how Block's engineers and anonymous researchers found the root cause within hours of the first reports being noticed.
Coinkite handled it right: fast advisory, detailed technical backgrounder within hours, immediate firmware patch with no new features, clear migration guidance. Transparency is the only play in Bitcoin.
But if you used one of these devices to generate keys in the last five years, transparency from the vendor doesn't put your coins back. Move them now.