COLDCARD vulnerability what happened, and what to do
Informational only, and this site never asks for your recovery words. details

Informational only. This is independent analysis and an evidence-backed explainer, not financial, security or legal advice, and not a substitute for professional advice about your own situation. It is not affiliated with, endorsed by, or speaking for Coinkite, Block, or any other party named here. Published estimates are attributed, and differing scenarios are kept separate with their assumptions. Act on your own judgement. Editorial standards and corrections.

Do not disclose recovery material to a website, form, message or support account. This site never asks for it. Deliberate recovery on independently verified offline equipment is a separate operation. Seed-word safety.

Plain language Updated 1 Aug 2026

Dice-generated and dice-mixed seeds

Pure-dice generation bypasses the affected generator. Mixed dice include its output as a prefix, then add the roll string through SHA-256.

No code. Written to be actionable.

COLDCARD supports two distinct dice workflows. Their security properties are not identical, so the number and quality of rolls matter alongside which workflow was used.

flowchart TB
  subgraph PURE["Pure dice: New Seed Words, Advanced, Dice Roll"]
    A1["empty starting value"] --> A2["SHA-256 over roll symbols"]
    A2 --> A3["12- or 24-word result"]
  end
  subgraph MIX["Mixed dice: add rolls on the word screen"]
    B1["device-generated seed prefix"] --> B2["SHA-256 over prefix and roll symbols"]
    B2 --> B3["updated seed"]
  end
    

The pure path does not call the affected generator. The mixed path does, but unpredictable rolls can add a separate source of uncertainty.

Pure dice

The code starts with an empty byte string and hashes the roll symbols. The affected ngu.random output is absent from this path.

The result is deterministic from the roll string, so it can be reproduced offline with an independently reviewed implementation. The roll string is equivalent to secret seed material and must not be entered into a website or connected computer.

Dice mixed into a generated seed

The code hashes the existing device-generated seed followed by the roll symbols. If an attacker can reproduce the prefix, the remaining search still includes the unpredictable roll sequence.

This path does not enforce the pure-dice roll thresholds, so its strength depends on the actual number, fairness, independence and secrecy of the rolls. Coinkite's advisory nonetheless applies the same 50-roll exception here, on those conditions, and the full digest becomes the seed.

Roll counts and output size

Entropy in fair independent six-sided-die rolls
Rolls Roll entropy Relevant output
50about 129.25 bitsThe enforced minimum for a standard 12-word pure-dice seed in the firmware state checked on 1 August 2026. The BIP39 entropy portion is 128 bits, so the output caps the result at 128 bits.
99about 255.91 bitsThe enforced minimum for a standard 24-word pure-dice seed in the firmware state checked on 1 August 2026, just below the 256-bit output size.
The screen shows the answer while you roll Every roll threshold on this page assumes the rolls were never recorded or exposed, and the device itself is one of the ways that condition can fail. While rolls are being entered, COLDCARD redraws the running SHA-256 digest on each pass of the input loop as 64 hexadecimal characters across two lines. Because both dice paths finish by assigning that same digest as the seed, the last value displayed on that screen is the resulting seed entropy, in the mixed workflow as well as the pure one. A photograph, a screen recording or a shoulder-surfer at the final roll therefore compromises the wallet even when no individual roll was ever written down. This is a handling hazard around the display, not a defect in dice mode: the construction itself is sound, and rolls kept private retain the entropy calculated above.

Warning and enforcement changed by workflow

Roll-count behaviour verified in affected firmware and the state checked on 1 August 2026
WorkflowBehaviour
v4.0.0 pure dice, 24 wordsWarned below 99 rolls, but allowed the user to confirm and continue.
Standard pure-dice seed, state checked 1 Aug 2026new_from_dice() enforces 50 rolls for 12 words and 99 for 24 words.
Ephemeral pure-dice seed, state checked 1 Aug 2026Warns below the same thresholds but still allows an override because it does not set enforce=True.
Dice mixed on the word screenDoes not enforce the pure-dice thresholds. Security depends on the number and quality of rolls actually entered.

The in-browser estimator can model pure dice as a replacement for the affected device path, or mixed dice as an independent term capped by the mnemonic output size.

The vendor's dice exception, and how it maps to the code

The Coinkite Mk3 advisory now states the mixed-dice construction and the roll threshold itself, under the heading "If You Added Dice When Creating the Seed". In the capture held from 1 August 2026, the page marked as updated at 9:35 a.m. EDT that day, it says that on affected firmware COLDCARD "hashed the device-generated seed together with every dice roll entered through Add Dice Rolls", that 50 to 98 independent private rolls contributed at least 128 bits and 99 or more contributed approximately 256 bits, and that where at least 50 fair and independent rolls were entered and "the rolls were not recorded or exposed", it does not consider the resulting seed at risk from this RNG issue alone. It attaches two limits: the exception applies to the final seed words shown after the dice were added, and anyone uncertain about which words they used, how many rolls they entered or whether the rolls were private is told to migrate.

The firmware matches that description. add_dice_rolls() builds a SHA-256 context from the seed it is given, updates it with each roll symbol as the symbol is pressed, and assigns the complete 32-byte digest back as the seed. Pure dice pass an empty starting value into the same function, so the two workflows differ only in the prefix. Nothing on this path is truncated. The vendor's statement about mixed dice is therefore supported by a construction this archive has read in the source, at the affected v4.0.0 release commit and at commit 9a88e1a5, rather than resting on the advisory alone. The separate roll-count arithmetic still depends on the output size: 50 rolls fill the 128-bit entropy input of a 12-word mnemonic, and a 24-word result needs 99.

The 50-roll figure reached the public before the vendor published it. Antoine Poinsot advised users that the dice-roll exception required at least 50 rolls, and Praveen Perera gave the same threshold while recommending migration after an independent recovery attempt, both on 31 July 2026. The dice section is absent from the earliest held state of the advisory, timestamped 01:56 UTC on 31 July and recovered from the Internet Archive, and present in every held state from 07:30 UTC that day onward. Those posts are retained as the earlier signal in time. They are no longer the basis for the rule, which the vendor has since stated in its own words.

A stricter 99-roll public rule

James O'Beirne recommended migration for coins spendable by one affected COLDCARD key, or by an affected-key quorum, when the device had been initialised with fewer than 99 dice rolls. He added that a strong passphrase could mitigate the risk while warning that most users cannot reliably judge passphrase strength.

That is a stricter incident-response rule than the public 50-roll exception. In the firmware, 99 rolls is the pure-dice threshold for a 24-word output, while 50 is the enforced threshold for a 12-word output. O'Beirne's post does not distinguish pure-dice generation from dice mixed into a device-generated seed. It is therefore retained as attributed advice, not as a replacement for the workflow-specific calculation above.

Conditions attached to the dice conclusion The calculation assumes a fair die, independent rolls, an accurately entered sequence and no disclosure of that sequence. Fewer rolls can still add useful uncertainty. The defensible bound is the smaller of the roll entropy and the output's entropy size, rather than a binary safe/unsafe label. Dice do not protect a seed if the roll sequence was photographed, backed up online or generated predictably, and, as above, the device's own running-digest display counts as a way of exposing it.
Why the 32-bit reseed truncation does not truncate the dice

add_dice_rolls() creates a SHA-256 context from the existing seed, updates it with each roll symbol and returns the digest. It does not call ngu.random.reseed(). The separate 32-bit truncation in shared/mk4.py therefore does not apply to the roll string.

Pure dice starts from an empty value. Mixed dice starts from the already generated seed. Both statements are verified in the affected implementation and in commit 9a88e1a5c32c69ba7ace7f22c26da90f8442b745, checked on 1 August 2026.

This is what allows the vendor's dice exception to reach the mixed workflow at all. If the roll string were folded through the truncating reseed rather than through this digest, added rolls could not carry the 128 or 256 bits the advisory credits them with.

Evidence and calculations are scoped beside the claims they support. Device-state attack-cost scenarios are compared in what an attack costs, with each source's assumptions written out. Where sources disagree, their scenarios are kept separate. If something here is wrong, say so.