The Coldcard incident: fixing the culture that missed it

A cultural failure: execution-path trust over evaluation, and social reputation over development quality.

armstrys

4. August 2026August 4, 2026 · 16 Min. Lesezeit16 min read

21

A cultural failure: execution-path trust over evaluation, and social reputation over development quality.

On July 30, 2026, someone started emptying Bitcoin wallets that had been dormant for years. No phishing, no malware, no compromised exchange. A five-year-old firmware bug had made the seed phrases guessable, and the attacker derived the private keys offline and swept the first wave of funds before anyone knew there was a problem.

This is not another write-up about the mechanics of the hack. The bug itself is almost boring: one check that tested whether a setting existed instead of whether it was turned on. What should raise eyebrows is that it lived for five years in open, widely-read code, inside the wallet the community trusted most, and nobody caught it. It went unnoticed because self-custody culture rewards the wrong things. It assumes a code path runs because the code is present, and it grades vendors on reputation instead of evidence. Those two habits, execution-path trust over verification and reputation over development practice, are the real vulnerability, and they will keep producing thefts like this one until the community trades trust for proof. What follows is less about Coldcard than about the standard that allowed it, and the one that has to replace it. The article closes with an example draft checklist that turns that standard into concrete questions you can put to any hardware wallet vendor.

Social media has reached for the easy lesson: self-custody is too hard, go back to letting a custodian hold the keys. That the average person recoils from self-custody in the short term is probably unavoidable. If it becomes a long-term trend, that will be because the Bitcoin ecosystem failed to correct its flawed culture around security.

Exchanges did not die after Mt. Gox and self-custody will not die after this. The exchange industry has evolved since Mt. Gox with multi-signature custody, proof-of-reserve practice, and regulatory structure that outlasted the operator who failed. Whether massive self-custody failures produce that kind of durable change is the open question. One-off audits are currently underway across every hardware wallet vendor, but the real lever is how we move forward when we talk about security in self-custody.

The bug, briefly#

Coldcard's board config defined the macro MICROPY_HW_ENABLE_RNG and set it to 0, because Coinkite supplies its own hardware RNG. A library the firmware migrated to in 2021 checked #ifndef MICROPY_HW_ENABLE_RNG, which asks whether the macro exists, not whether it is switched on. The macro existed. The build linked MicroPython's software fallback PRNG, a toy generator meant for chips with no hardware RNG at all. The real hardware RNG code stayed in every affected binary, reviewed and intact. Seed generation simply never called it.

Coinkite puts effective entropy on Mk2 and Mk3 devices running firmware v4.0.1 through v4.1.9 at roughly 40 bits against a 128-bit design target. Forty bits is a weekend on commodity hardware. Block Engineering's independent analysis is worse: depending on what an attacker already knows about the device UID and boot timing, the practical search space collapses toward 2^16, and the reseed on later models is capped at 32 bits because only four digest bytes ever reach it. Coinkite's figure for Mk4, Q, and Mk5 is about 72 bits, still under the standard and inside the budget of a funded attacker.

Entropy generation is the critical step in self-custody that has no replacement. The seed is the root of every key the wallet will ever derive, so a perfect PIN, textbook multisig, and a signing screen that shows exactly what you are approving all rest on top of it, and none of them can save a seed an attacker can guess. That is why this one step is worth staring at while the rest of the device goes unmentioned.

That is the entire technical story, and it is the least interesting part of the incident. The bug is ordinary. What matters is that it shipped, passed review, survived a test suite, and sat in public source for five years underneath the device the community told everyone to buy.

Where the process broke#

The development practices at Coinkite failed to catch this. The commit that introduced the bug, b18723dd on March 1, 2021, changed 120 files and 5,488 lines, swapped out the cryptographic primitives under seed generation and signing, and went straight to master with the message "First pass w/ libNgU." The public history shows a single-parent commit with no merge, no pull request, and no CI run. A change to seed generation reaching users with no formal, published review process is not a one-off slip; it is a process with limited gates and no transparency.

Testing the output for entropy is nearly impossible, and that is the trap. The suite set random.seed(42) for reproducibility, and the only runtime check asserted a handful of distinct byte values, which any deterministic generator passes. No statistical test on a finished seed can separate unpredictable from reproducible: a 40-bit seed still expands into unique, normal-looking addresses. Entropy is a property of the process, not the bytes. What is tractable is testing the path, which nobody did: confirm the hardware RNG is actually reached, and that known inputs produce known outputs. Block Engineering found the failure there in hours. The hardware RNG exported different function names than the library expected, so the call bound to MicroPython's software generator instead, and the correct code sat present and unreachable in every binary. It is the unverified backup: file there, checksum fine, empty the day you restore from it.

A closed secure element adds a variable you cannot account for. The reseed on Mk4, Q, and Mk5 comes from a chip whose firmware nobody outside Coinkite can audit, so the 72-bit figure rests on trust rather than measurement. Reproducible builds prove the shipped binary matches the public source, which matters, but they cannot tell you the source is correct, and they cannot let you feed known entropy into the secure element and check what comes back. Every closed component in the entropy path is one more thing taken on faith.

Most importantly, the "grading" of Coinkite as a reliable provider was done on reputation. Coldcard was the default recommendation for years, sold on marketing, feature lists, and word of mouth, and that recommendation was never attached to anything a buyer could inspect. Nobody traced the call path because everybody assumed somebody already had. That is the habit that has to change. A recommendation should turn on the strength of the development team, whether the code and build can actually be audited, the quality of the tests, and how much trust the design removes from any single part. Reputation without clear evidence is nothing but trust.

What vendors should do to improve validation#

None of these are hard asks. Most are a weekend of engineering time, and the first three would have increased the odds of catching the bug.

What the community has to demand#

The audit wave now underway is the right instinct running on the wrong standard. Ledger has said its certified TRNG is unaffected. Trezor has said it does not share Coldcard's code. Keystone, Foundation, and BitBox have issued similar statements. Every one of those is a claim, and Coldcard would have made the identical claim on any day of the last five years.

The question each vendor needs to answer is narrow and checkable: can you trace the entropy path from source to seed, end to end, on the actual shipped binary, and show that the hardware RNG is reachable from make_new_wallet or its equivalent? "We have a TRNG and it is in the code" is the answer that failed.

Open-source vendors have an advantage in answering this question, and should use it. Producing that trace means publishing the source path, the symbol resolution on the built binary, and the known-answer test vectors, none of which exposes a proprietary secure-element design. The closed part can stay closed; the entropy path can still be shown. A vendor that answers "trust our certification" when it could publish the trace is choosing opacity it does not need, and that choice should count against it.

Three levels of assurance need separate names, because collapsing them is how this happened.

Coldcard had the first two. Almost every discussion of hardware wallet security treats the first two as sufficient, which is the problem we need to fix now.

Two structural changes would make the validation process normal rather than heroic:

This is at least the second time a bug like this has produced weak seeds at scale. In 2023, Milk Sad (CVE-2023-39910) revealed that Libbitcoin Explorer's bx seed used a Mersenne Twister seeded from 32-bit time(), exposing 120,000 keys. Same root cause, same cultural failure: open source, publicly documented, nobody auditing the entropy path. The response was to fix Libbitcoin, warn users, and move on. That response worked once and cannot work twice. Every wallet that generates keys needs its entropy path traced on every release, and the traces need to be published.

Holders also have two levers to pull to mitigate risk in key generation: multi-vendor multisig and bring your own entropy (dice, coins, etc.). Both mechanisms reduce the reliance of wallet security on any single vendor's implementation. In Coinkite's case, multisig and dice-roll users are thought to be unaffected by this exploit. Critics will say that dice rolling can be unreliable. The reality is that the current state of industry means users either roll their own, or trust a vendor. The only way to actually improve this dynamic is to make it easier for users to verify the validity of entropy from a hardware wallet. Even with these options as part of the equation a robust future of self-custody heavily relies on the community getting the culture around vendor/code evaluation correct.

The pressing challenge of AI#

Everything above points one direction: transparency is the advantage. A vendor that shows its work, in the code and in the build, needs less trust from the buyer, and needing less trust is the entire point of self-custody. But open code cuts both ways. Anyone can read it, which means anyone can also hand it to a frontier model.

Any code that has ever been public is now scannable by an attacker with a current model, across the full commit history, faster than any human review team can work. The five-year dormancy window that let this bug survive is closing, and it closes for every project at once. A clean audit in 2024 says nothing about 2026, because the tool doing the reading keeps getting better. Auditing becomes maintenance, not a milestone.

Hiding the source is the wrong reaction. Closed code delays attacker discovery, and delays defender discovery by more, because you find your own bugs only when the funds are already gone. The economics point the same way: AI review at scale runs into real token bills, and an open project can spread that cost across a community while a closed vendor pays alone and cuts corners in private. What fits the moment is a shared audit framework, one that lets the community hunt vulnerabilities early and often: full re-audits each time a more capable model ships, and AI-assisted review on every pull request, with human oversight and discussion before anything merges.

Moving Forward#

It is tempting to lay this on Coinkite alone, or on the people who recommended the device for years. The blame is wider than that. Bitcoin worked. Self-custody worked. What failed sat around them: a critical bug in plain sight in public code, under a device holding a large share of the community's savings, and no habit anywhere in the ecosystem was going to catch it.

That culture is being rebuilt now and our discussions will shape it. Over the next few months the audits underway will continue in two possible directions: traced entropy paths, published test vectors, and symbol resolution checked against real binaries, or another round of reassuring press releases from vendors. The Coldcard incident proved that the Bitcoin community had largely been trusting and not verifying, despite the common mantra to do the opposite.

This is not the time to recoil from our stated values. It is the time to shift from trust to verification. One preprocessor check tested the wrong thing for five years and nobody looked, because nobody had to; reputation stood in for proof. The wallets that deserve trust after this are the ones that never ask for it, the ones that hand you the proof and let you run it yourself.

Appendix: Example Hardware Evaluation Framework#

Everything above reduces to one question a buyer or reviewer can put to any vendor: can you show, not assert, that the secure path runs? The checklist below turns that into concrete asks. A vendor's answers sort them into the three assurance levels, and a "no" in the entropy-path section should count for more than a polished answer everywhere else.

Assurance level

The entropy path

Development process

Testing

Closed components

Generation-time evidence

Track record

Written by

Comments

No comments yet. Start the conversation.

Contents

7 sections

  1. The bug, briefly
  2. Where the process broke
  3. What vendors should do to improve validation
  4. What the community has to demand
  5. The pressing challenge of AI
  6. Moving Forward
  7. Appendix: Example Hardware Evaluation Framework