Updated August 1, 2026 at 2:35 p.m. EDT: Funds controlled by seeds generated on affected firmware are at risk if the seed was created without at least 50 independent, private dice rolls and the funded wallet is not protected by a strong, unique BIP-39 passphrase.
Fixed firmware is now available for every affected model and release track, including Edge firmware versions 6.6.0X for Mk4/Mk5 and 6.6.0QX for Q.
What You Should Do
The passphrase must be strong, unique, secret, and separate from the seed backup. A short, common, patterned, quoted, reused, exposed, or uncertain passphrase does not qualify; treat those funds as at risk. Even when a strong passphrase reduces the immediate exposure, it does not repair an affected seed. Unless the independent dice-entropy exception applies, replace the seed and migrate as soon as practical.
If your seed was generated on a Mk2 or Mk3 running firmware 4.0.1 through 4.1.9 without at least 50 independent, private dice rolls:
- Update the Mk2 or Mk3 to firmware version 4.2.0 or later before generating a replacement seed.
- Generate a completely new seed on the updated COLDCARD.
- Record and verify the new backup, wallet fingerprint, and a receive address.
- Send a small test transaction before moving the remaining funds.
- Keep the old backup until the migration is complete and confirmed.
Follow the dedicated Mk2/Mk3 Security Advisory and migration instructions. Proceed calmly and verify every step.
If you added at least 50 fair, independent, private dice rolls when originally creating the seed, read the dice guidance in the advisory before migrating. We do not consider that seed at risk from this RNG issue alone.
If your seed was generated on affected Mk4, Mk5, or Q firmware without at least 50 independent, private dice rolls:
- Upgrade to the fixed firmware for the release track you use before generating any new seed:
- Generate a completely new seed on the updated COLDCARD.
- The fixed firmware’s device-generated seed is sufficient. Dice rolls are optional and are not required to address this issue. A BIP-39 passphrase is a separate wallet-security choice.
- Back up the new seed and any passphrase carefully. Store the passphrase separately from the seed words.
- Power-cycle the COLDCARD and verify the wallet fingerprint and a receive address.
- Send a small test transaction before moving the remaining funds.
Updating the firmware does not repair a seed that was generated by affected firmware. A new seed must be generated and the funds migrated to the new wallet.
Standard and Edge are separate release tracks. If you use Edge, install the fixed Edge release for your model. Do not assume an older Edge 6.x release is fixed merely because its version number is higher than the standard release.
A passphrase creates a different wallet. Every passphrase—including one containing a typo—produces a valid wallet, so verify the wallet fingerprint before depositing funds. Losing the passphrase means losing access to that wallet.
Read the COLDCARD passphrase instructions and dice-roll instructions before using either option.
TAPSIGNER, OPENDIME, and SATSCARD are not affected because they use different codebases.
Summary
A complex and subtle series of bugs prevented the hardware RNG from contributing randomness in certain versions of the firmware. We were unaware of the bug until today. Changes introduced for Mk4 added entropy from SE1 and SE2, which partially reduced the impact on later models but did not restore the intended 128-bit security target.
The COLDCARD source code has always been open and publicly available, so we have to assume that someone used AI to review previous versions of our firmware and stumbled upon this issue. A few weeks ago, we used one of the best available AI models to review our code for security issues, and it did not find this bug or anything serious.
Both attackers and defenders have the same AI tools, but today it did not help us, and only helped the bad guys.
For funded wallets with neither the independent dice entropy nor a strong, unique BIP-39 passphrase described above, the reduced search space is a direct security risk, not a theoretical possibility.
Technical Background
In 2021, we moved COLDCARD’s elliptic-curve operations to Bitcoin Core’s
libsecp256k1, using the same implementation trusted by Bitcoin Core instead
of maintaining a separate EC stack. That required adding libNgU, an embedded
MicroPython library that exposes libsecp256k1 and other Bitcoin primitives.
The cryptographic choice was sound. The integration was not. During that
migration, wallet seed generation moved from ckcc.rng_bytes() to
ngu.random.bytes(). That path resolved rng_get() to MicroPython’s software
fallback instead of COLDCARD’s hardware RNG implementation.
The bulk of randomness on the COLDCARD was coming from a PRNG that I didn’t know was actually in the source code base (it is from a submodule, Micropython). At the same time the carefully crafted TRNG code I wrote was being used, but just by chance, and only for less important things.
On Mk2 and Mk3, the active PRNG was seeded primarily from device and timing state. Under our current attack assumptions, we estimate the effective search space at about 40 bits. This is a preliminary estimate and may change as analysis continues.
During Mk4 development, we also mixed values from the TRNGs in SE1 and SE2 into the PRNG state as a backup to a backup. This additional entropy materially improves the situation for Mk4, Q and Mk5. Under the same current assumptions, we estimate the effective search space at about 72 bits.
Although Mk4, Q and Mk5 had additional secure-element entropy mixed into the PRNG state, they continued to draw most subsequent random values from the same MicroPython PRNG:
That file either builds PRNG code, or uses the STM32 hardware TRNG. Looking
quickly at it, you’d think we got the TRNG version of get_rng()
but in fact, I explicitly set MICROPY_HW_ENABLE_RNG to zero, thinking
we didn’t need either version, but that’s not what it does. Because
that code provided a PRNG with the same function signature as
the desired code, the build completed without identifying the wrong
implementation.
The MicroPython fallback was introduced upstream in May 2018. It did not enter COLDCARD wallet seed generation until the libNgU migration in March 2021. The affected Mk2 and Mk3 firmware range is 4.0.1 through 4.1.9. Version 4.2.0 corrects new seed generation. The eight-year figure therefore describes the age of the upstream fallback code, not the duration of affected COLDCARD seed generation.
Existing review confirmed that the intended TRNG implementation was present in
the firmware binary, but did not verify which rng_get() implementation the
wallet seed-generation path actually reached across the two submodules. No
changes are needed in the COLDCARD firmware itself, just which code comes along
for the ride.
Why Existing Review Did Not Catch It
Both RNG implementations had the same function signature, and the intended board-specific TRNG code was present in the binary. Existing review verified that code but did not verify end-to-end symbol resolution and call reachability from wallet seed generation.
The relevant preprocessor guard is visible in this section of code:
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 hotfix now explicitly excludes MicroPython’s fallback PRNG object and adds
a build-time RNG symbol check. The build fails unless the board-specific object
defines the global rng_get() symbol and the upstream fallback object defines
no symbols.
Next Steps
We have released emergency hotfixes for every affected model and release track:
- Version 4.2.0 for Mk2 and Mk3
- Standard version 5.6.0 for Mk4 and Mk5
- Standard version 1.5.0Q for Q
- Edge version 6.6.0X for Mk4 and Mk5, and Edge version 6.6.0QX for Q
These hotfixes correct entropy generation. Updating does not repair seeds that were generated by earlier affected firmware; those seeds must still be replaced unless the independent dice-entropy exception applies.
At this point, many researchers and competitors have studied this bug and published their own analysis: