Coldcard vulnerability

Coldcard vulnerability

Origin of the Weakness

The evidence points to a cascading series of events rooted in a license change, which created the conditions for a subtle but devastating build-integration bug. There is significant community debate about whether this was gross negligence, collateral damage from corporate decisions — or something more suspicious. Here's what the evidence shows:

The Technical Bug

The core vulnerability was a link-time symbol resolution error that silently replaced Coldcard's hardware True Random Number Generator (TRNG) with MicroPython's Yasmarang software PRNG — a non-cryptographic pseudorandom number generator seeded only from the chip's unique ID and timer registers [1][2].

The mechanism worked as follows:

  • Coldcard's production config defined MICROPY_HW_ENABLE_RNG as zero (#define MICROPY_HW_ENABLE_RNG (0)), intended to disable MicroPython's software RNG path since Coldcard supplied its own hardware RNG wrapper [3].
  • However, the libngu library's preprocessor guard used #ifndef — which checks whether the macro is defined, not whether its value is nonzero. Since the macro was defined (as zero), the guard passed, and the build compiled in the software PRNG fallback instead of stopping with an error [3:1][4].
  • Meanwhile, libngu called rng_get(), which resolved at link time to MicroPython's stm32 PRNG implementation rather than Coldcard's intended hardware rng_get_or_fault() function. Both functions had the same signature, so the build completed without any missing-symbol errors [1:1].
  • The result: seed generation dropped from 128 bits of entropy to approximately 40 bits on the Mk3 (~72 bits on some other models), making seeds brute-forceable [5].

The License Change: The Catalyst

This is where the "suspicious happenings" you've heard about come in. The evidence strongly connects the vulnerability to Coinkite's decision to abandon true open-source licensing:

Date Event
July 2020 Foundation Devices releases the Passport wallet by legitimately forking Coldcard's GPL-licensed firmware. Coinkite CEO NVK publicly regrets choosing the GPL: "now we have a clone" [5:1].
Late 2020 / Early 2021 Coinkite switches from GPL to MIT + Commons Clause — "source available" but not truly open source, preventing competitors from using the code commercially [5:2][6].
March 1, 2021 A massive 120-file commit titled "First pass w/ libNgU" removes the remaining GPL-licensed Trezor-derived crypto libraries and replaces them with libNgU (licensed under a novel "Licensed for Bitcoin Only" license). The entropy bug was introduced in this exact commit [5:3][7].
May 21, 2021 Coinkite CTO doc-hex commits a change incorporating #define MICROPY_HW_ENABLE_RNG (0) — the line that inadvertently disabled the hardware RNG for seed generation [8].
2021 – July 2026 The flaw persists undetected for 4+ years [9].
April–May 2026 Attacker sends dust transactions to the largest vulnerable addresses — target marking indicating the attacker had the list of vulnerable seeds at least 3 months before the attack [5:4].
July 30, 2026 Between 01:10 and 01:51 UTC, 1,082+ BTC (~$70M) drained from 1,196 addresses in 41 minutes. Losses eventually exceeded $114M [2:1][10].

The Chain of Causation

The evidence establishes a clear causal chain:

  1. A competitor legally forked Coldcard's GPL code → Coinkite felt commercially threatened
  2. Coinkite changed the license to kill commercial copies → requiring removal of all GPL-licensed code
  3. The massive GPL-removal refactor (the 120-file libNgU commit) → introduced the entropy bug as collateral damage
  4. The restrictive license reduced community auditing → fewer eyes on the code meant the bug survived for 4+ years

As one analysis put it: "coldcard decided to move from open source licensing to a 'source available' license that would prevent people from forking their firmware to make competing products. This meant they needed to replace GPL license crypto libraries, it is this refactoring that created the opportunity for them to screw up" [7:1].

The same source notes: "Our best understanding right now is that the entropy bug was collateral damage from this major overhaul of the codebase" and "the entropy bug was introduced inside the same 120-file commit that removed the old GPL code dependencies" [7:2].

Coinkite's Official Position

Coinkite's own technical blog states:

"There was no intentional weak-entropy fallback."
"Setting MICROPY_HW_ENABLE_RNG=0 was intended to disable the software path. A build and link integration error meant that setting did not have the intended effect."
"This was inherited platform behavior activated by a link-time error, not an intentional seed-generation design decision or shortcut."

They acknowledge the developer explicitly set the macro to zero "thinking we didn't need either version, but that's not what it does" and that 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" [3:2].

The Suspicious Elements & Community Skepticism

Several factors have fueled suspicion beyond mere incompetence:

  • The bug appeared in the exact commit that removed GPL code — the license-change refactor was the vector [7:3].
  • The restrictive license suppressed independent auditing — as one analyst noted, "The new restrictive license has sharply reduced the number of people motivated to deeply audit the code. Fewer eyes = the bug survives!" [5:5].
  • The attacker appeared to have insider-level knowledge — dust transactions 3 months before the sweep targeted only the largest balances, suggesting the attacker had pre-computed vulnerable seeds well in advance [5:6].
  • NVK's behavior during the crisis — Reddit posts flagged that Coinkite's CEO was tweeting about unrelated topics during the emergency and deleting tweets, which some interpreted as evidence he was unaware (or evasive) [11].
  • "Retirement Attack" theory — a widely-discussed Reddit post argued that multiple details "point straight to Coinkite" as potentially responsible, framing it as a deliberate "retirement attack" [12].
  • "Inside job" allegations — some speculated that if Coldcard planned this, they could have targeted YouTube influencers with sponsorship deals for maximum outreach to increase the number of affected users [13].
  • The attacker's one mistake — they used a paid account with a major blockchain data provider whose logs match the attack "down to the second," potentially providing KYC evidence for authorities [5:7].

Bottom Line

What the evidence clearly establishes: The weakness originated directly from Coinkite's decision to abandon the GPL in favor of a restrictive "source-available" license. The 120-file commit that removed GPL-licensed code introduced the entropy bug. The license change was both the cause of the buggy refactor and the reason the bug went undetected for years (by suppressing independent auditing). Coinkite acknowledges the bug was introduced during the libNgU migration but insists it was an unintentional build-integration error.

What remains disputed: Whether the bug was pure incompetence/collateral damage (Coinkite's position, supported by the plausible technical mechanism) or something more deliberate (the "retirement attack" / inside job theories circulating on Reddit and social media). The suspicious elements — the precise coincidence with the GPL removal, the reduced auditing from the license change, the attacker's apparent insider-level preparation, and NVK's behavior — are circumstantial. No hard evidence of intentional backdooring has been publicly proven, but the causal link between the license change and the vulnerability is well-documented and widely accepted.

References


  1. Coldcard postmortem from MicroPython's perspective · micropython · Discussion #19588 · GitHub (7%) ↩︎ ↩︎
  2. Coldcard Hardware Wallet Flaw Linked to $70 Million ... (6%) ↩︎ ↩︎
  3. Technical Deep Dive into the Entropy Issue | COINKITE Blog (13%) ↩︎ ↩︎ ↩︎
  4. Coldcard Hardware Wallet Hack: Everything You Need to Know (5%) ↩︎
  5. How the Coldcard Bug Was Born and Exploited (25%) ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
  6. Coldcard is not "Open source" : r/Bitcoin (4%) ↩︎
  7. Attempting to remove OSS licenses is why coldcard firmware became vulnerable - BOCVIP (20%) ↩︎ ↩︎ ↩︎ ↩︎
  8. Coldcard Firmware Flaw Exposes Millions in Crypto Losses | LinkedIn (4%) ↩︎
  9. ️ Firmware and simulator for Coldcard Hardware Wallet (1%) ↩︎
  10. Coldcard Wallet Losses Near $114 Million as a Fourth... - Genfinity (2%) ↩︎
  11. What's ColdCard's CEO doing during an emergency? He's ... (5%) ↩︎
  12. Retirement Attack: Many more details pointing straight to ... (4%) ↩︎
  13. COLDCARD Wallet exploit was an inside job (4%) ↩︎