# The COLDCARD RNG Vulnerability: How a “Random” Bitcoin Seed Became Guessable

*D. Rose · 15 August 2026 · 29 min*

> A plain-language teardown of the 2026 COLDCARD RNG flaw: how a firmware integration mistake pushed wallet generation onto a deterministic software PRNG, why the public blockchain let attackers verify guesses for free, why an air-gapped device did not help, and why a firmware update cannot repair a seed that was already generated.

```glossary
TRNG: True Random Number Generator — draws randomness from physical hardware behaviour (thermal/electrical noise). The gold standard for a wallet secret.
CSPRNG: Cryptographically-Secure PRNG — a PRNG designed so its output cannot be predicted even given earlier output.
PRNG: Pseudo-Random Number Generator — an algorithm that expands a small internal state into a long random-looking stream. Deterministic: same state, same output.
RNG: Random Number Generator — hardware or software that produces values meant to be unpredictable.
entropy: A measure of unpredictability — effectively how many truly-random bits stand behind a value. ~256 bits is unguessable; ~40 bits is not.
deterministic: Given the same input or internal state, it always produces the same output — no randomness involved.
seed phrase: A human-readable list of words (BIP-39) that encodes a wallet's master secret. Anyone who reconstructs it controls the coins.
BIP-39: The Bitcoin standard mapping a block of initial entropy to a mnemonic word list (and back), with a checksum.
master private key: The single secret from which every one of a wallet's keys and addresses is derived.
candidate-validation oracle: Anything that lets an attacker confirm whether a guessed seed is correct. Here, the public blockchain plays that role for free.
air-gapped: Never connected to any network — data moves only by QR code or SD card. Protects the secret from extraction, not from independent reconstruction.
Yasmarang: A small, fast, non-cryptographic PRNG. Fine for simulations; unsafe as the source of a wallet secret.
```

**A hardware wallet can be completely offline, your seed phrase can never leave the device, and an attacker can still steal your Bitcoin — if the seed was never truly random to begin with.**

That is essentially what happened with the 2026 COLDCARD RNG vulnerability.

This one is confusing because phrases like **RNG**, **entropy**, **PRNG**, **seed phrase**, **private key**, and **deterministic output** get thrown around together. Then someone says:

> “Attackers brute-forced the seed.”

And the natural reaction is:

**Wait. They guessed 24 random words?**

Not exactly.

That distinction is the entire vulnerability.

---

### Reading Promise

By the end of this, you should understand:

- What an RNG actually does.
- What "entropy" means.
- Why Bitcoin wallets need randomness.
- How a perfectly normal-looking 24-word seed phrase can still be weak.
- What went wrong inside COLDCARD.
- What "deterministic" means here.
- Whether attackers were literally guessing seed phrases.
- How attackers could know when they had found a real wallet.
- Why Bitcoin's public blockchain actually helps the attacker verify guesses.
- Why an offline hardware wallet didn't prevent this.
- Why updating the firmware does **not** fix an already-created wallet.
- Why dice rolls and BIP-39 passphrases change the equation.
- Which COLDCARD models and firmware are affected.

No assumed Bitcoin cryptography knowledge.

---

## The 30-Second Version

A Bitcoin wallet starts with a secret random number.

That random number ultimately produces your:

```text
random number
      ↓
seed phrase
      ↓
master private key
      ↓
private keys
      ↓
public keys
      ↓
Bitcoin addresses
```

The security assumption is simple:

> The original random number is so unpredictable that nobody else could possibly generate it.

COLDCARD intended to generate that randomness using a **hardware True Random Number Generator**, or TRNG.

But because of a firmware integration mistake introduced around the 2021 code migration, wallet generation on affected firmware ended up using a **deterministic software pseudorandom number generator** in a way COLDCARD did not intend. On Mk2/Mk3 devices, important inputs to that generator came from things such as device and timing state rather than strong cryptographic randomness. Later devices added secure-element randomness, but not enough of it reached the relevant generator state to restore the intended security margin. 

So instead of:

```text
An astronomically huge universe
of possible wallets
```

attackers could potentially work with:

```text
A much smaller family
of wallets the buggy software
was capable of producing
```

Then they could do something extremely important:

```text
Candidate seed
     ↓
derive Bitcoin address
     ↓
look at public blockchain
     ↓
Does this address contain Bitcoin?
     ↓
YES → candidate is correct
NO  → try another
```

They did **not** have to ask the COLDCARD whether their guess was correct.

Bitcoin itself gave them the answer.

Block's researchers describe a wallet xpub, address, or public key as a **candidate-validation oracle**: something that lets an attacker determine whether a candidate seed is correct. 

That is the vulnerability in one picture.

---

## Part 1: Forget Bitcoin for a Second

Imagine I tell you:

> I'm thinking of a number.

You ask:

> Between what and what?

I answer:

> Between 1 and 340,282,366,920,938,463,463,374,607,431,768,211,456.

Good luck.

That number is approximately:

```text
2^128
```

There are about:

```text
340 undecillion possibilities.
```

Brute forcing that is effectively impossible.

Now imagine that I **claim** to choose from that enormous range, but because of a software bug my number generator really behaves more like:

```text
pick one of a much smaller,
predictable family of numbers
based partly on:

- the device
- the clock
- timing information
- known internal state
```

My output might still *look* like:

```text
183749108374910283749...
```

It looks random.

But looking random and **being unpredictable** are two very different things.

That distinction is fundamental to cryptography.

---

## Part 2: WTF Is an RNG?

RNG simply means:

**Random Number Generator.**

Cryptography constantly needs unpredictable numbers.

Passwords.

Encryption keys.

TLS session keys.

Authentication tokens.

Private keys.

Bitcoin wallets.

The important property isn't really:

> "Does this number look messy?"

It is:

> **Could somebody else predict or reproduce it?**

---

### TRNG vs PRNG

There are two terms worth knowing.

#### TRNG

**True Random Number Generator**

A hardware TRNG gets randomness from some physical phenomenon inside the hardware.

Very simplified:

```text
physical electrical behavior
          ↓
       measured
          ↓
    unpredictable bits
          ↓
101101000101110101101...
```

COLDCARD devices contain hardware intended to provide this kind of entropy. 

---

#### PRNG

**Pseudorandom Number Generator**

A PRNG is an algorithm.

Give it some starting state:

```text
State = 12345
```

and it produces something that looks random:

```text
48172918
98217341
01749102
...
```

But run the same algorithm with the same starting state again:

```text
State = 12345
```

and you get:

```text
48172918
98217341
01749102
...
```

Again.

That is what **deterministic** means.

Same starting conditions:

```text
INPUT A
   ↓
algorithm
   ↓
OUTPUT B
```

will give you:

```text
INPUT A
   ↓
same algorithm
   ↓
OUTPUT B
```

every time.

---

## Important: PRNG Does NOT Automatically Mean Insecure

This matters.

Modern cryptography routinely uses **cryptographically secure pseudorandom number generators**, or CSPRNGs.

Those are designed specifically so that knowing previous outputs doesn't make future outputs practically predictable.

So the COLDCARD problem was **not simply:**

> "They used software randomness. Software randomness bad."

That would be wrong.

The problem was the particular generator path, how it was initialized, and how secure entropy was — or was not — incorporated.

COLDCARD's affected firmware unexpectedly reached MicroPython's **Yasmarang** software generator instead of the intended hardware RNG path. 

That brings us to the bug.

---

## Part 3: What Is "Entropy"?

Entropy is one of those words security people make sound more complicated than it needs to be.

For our purposes:

> **Entropy is unpredictability.**

More entropy:

```text
more possible unknown states
              ↓
harder for attacker to guess
```

Less entropy:

```text
fewer possible unknown states
              ↓
easier for attacker to search
```

Think of passwords.

This password:

```text
password1
```

contains very little useful unpredictability.

This:

```text
jN8#vQ2!fzP6$LmX
```

contains considerably more.

Both are strings.

Both could be stored in the same password field.

Their **appearance as a string doesn't tell you the size of the attacker's search space**.

Seed phrases work similarly.

---

## Part 4: Your 24 Words Aren't the Magic Part

People naturally think the 24 words themselves provide the security.

They don't.

The **randomness behind the words** provides the security.

BIP-39 essentially takes binary entropy and turns it into human-manageable words. Under BIP-39, a 24-word mnemonic encodes 256 bits of initial entropy plus checksum information. 

Conceptually:

```text
101110001001011101001010...
             ↓
           BIP-39
             ↓
"apple ... bicycle ... volcano ..."
```

The words are an encoding.

---

### Imagine This

Suppose I wrote software that does this:

```text
Choose one random number between 1 and 100.
```

Then I take the number and run it through an algorithm that turns it into a beautiful 24-word Bitcoin seed phrase.

I might get:

```text
word word word word word word
word word word word word word
word word word word word word
word word word word word word
```

It **looks exactly like a real wallet seed.**

But there were only:

```text
100
```

possible seeds my program could ever generate.

An attacker wouldn't need to test the astronomical universe of all 24-word phrases.

They would need to test:

```text
Seed candidate #1
Seed candidate #2
Seed candidate #3
...
Seed candidate #100
```

The formatting doesn't restore the lost randomness.

Neither does hashing it afterward.

Block specifically noted this problem with the affected COLDCARD design: hashing the RNG output can make the resulting bytes *look* uniformly distributed, but hashing cannot magically increase the number of possible starting states. 

In other words:

```text
100 possible inputs
        ↓
      SHA-256
        ↓
still at most
100 possible outputs
```

Not:

```text
100 inputs
    ↓
SHA-256
    ↓
OMG NOW 2^256 POSSIBILITIES
```

Cryptography doesn't work like that.

---

## Part 5: So What Actually Went Wrong With COLDCARD?

This is where the story gets interesting.

COLDCARD already had code capable of accessing its hardware random-number generator.

The hardware RNG itself wasn't simply sitting there producing bad numbers.

Instead, this was essentially a **software integration / build problem**.

COLDCARD describes it as a link-time integration error rather than a hardware TRNG failure. 

---

### Before the Regression

Earlier wallet generation used a path conceptually like:

```text
New Wallet
    ↓
COLDCARD hardware RNG
    ↓
random bytes
    ↓
wallet seed
```

Block traced the earlier code to a function using the board's hardware RNG directly. 

---

## Then Things Changed

Around the March 2021 migration to `libNgU`, wallet generation changed from the previous hardware-RNG call to something effectively resembling:

```text
ngu.random.bytes(32)
```

The expectation was that the underlying RNG path would ultimately reach the appropriate hardware random-number implementation.

But it didn't.

A configuration value existed:

```text
MICROPY_HW_ENABLE_RNG = 0
```

The intent was essentially:

> We aren't using MicroPython's RNG implementation because COLDCARD provides its own.

But another component checked whether that setting was **defined**, rather than checking whether it was **enabled**.

Conceptually, think:

```text
Is MICROPY_HW_ENABLE_RNG defined?
```

instead of:

```text
Is MICROPY_HW_ENABLE_RNG actually enabled?
```

Since:

```text
MICROPY_HW_ENABLE_RNG = 0
```

is still technically **defined**, the check passed.

The build succeeded.

And the wrong RNG implementation was linked into the path used by wallet generation. 

This is a wonderfully awful example of why security failures can happen several layers away from the actual cryptography.

The cryptographic algorithm wasn't necessarily broken.

The hardware wasn't necessarily broken.

The compiler wasn't necessarily broken.

The individual pieces largely did what they were programmed to do.

They were just connected incorrectly.

---

## Part 6: What Did It Use Instead?

MicroPython's fallback implementation used a software generator called **Yasmarang**.

Its initialization incorporated values including things such as:

```text
device UID
     +
system tick/timer state
     +
real-time-clock state
```

Block's analysis shows the fallback being initialized from the MCU UID and timer-related registers. 

Those values can certainly change.

But:

> **Changing does not mean cryptographically random.**

Consider:

```text
Current time:
3:14:27 PM
```

That changes every second.

It isn't random.

Likewise:

```text
Device serial number:
1234567
```

might be unique.

But unique isn't random either.

---

## Unique ≠ Secret ≠ Random

These are different concepts.

```text
DEVICE SERIAL NUMBER

Unique?        Maybe yes.
Secret?        Not necessarily.
Unpredictable? Not necessarily.
Random?        Not necessarily.
```

That's hugely important.

A cryptographic secret needs unpredictability.

---

## Part 7: What Does "Deterministic Output" Actually Mean?

This is where the earlier confusion usually happens.

It does **not** mean:

> Every COLDCARD generated the same seed.

And it does **not** mean:

> There were only 10 possible COLDCARD seeds.

It means that if an attacker can reproduce or sufficiently constrain the relevant starting conditions, the resulting software RNG stream can also be reproduced.

Very simplified:

```text
Device state
UID
Timer
RTC
Previous RNG activity
      │
      ▼
  Yasmarang
      │
      ▼
random-looking bytes
      │
      ▼
Bitcoin seed
```

If the attacker can determine enough of:

```text
Device state
UID
Timer
RTC
RNG-call history
```

then instead of asking:

> "Which seed out of essentially the entire universe did Dan get?"

the question becomes more like:

> "Which output could this known algorithm have produced under the plausible starting conditions?"

That is an enormously different problem.

Block explicitly cautions that this doesn't mean every attacker can instantly recover every seed. Practical attack cost depends on how well things such as UID information, timer state, prior RNG calls, and other conditions can be constrained. 

But the security model has already changed dramatically.

---

## Part 8: Are Attackers Guessing Seed Phrases?

Sort of.

But saying:

> "They guessed the seed phrase."

gives the wrong mental model.

The attacker doesn't necessarily sit there doing:

```text
abandon apple zebra horse...
NO

window table dog pizza...
NO

correct battery bitcoin...
NO
```

trying random words.

Instead, the attack is conceptually:

```text
Reproduce buggy RNG behavior

          ↓

Generate candidate entropy

          ↓

Convert candidate into the same
wallet structure COLDCARD would

          ↓

Derive Bitcoin keys

          ↓

Derive Bitcoin addresses

          ↓

Compare those addresses
with known blockchain activity
```

The "guessing" happens much earlier.

They're guessing or enumerating **possible RNG states/outputs**.

The seed phrase simply falls out of the process.

---

## Part 9: But How Does the Attacker Know Which Guess Is Correct?

This is the clever part.

Bitcoin addresses are public.

Bitcoin transactions are public.

The blockchain is public.

Suppose the attacker generates:

```text
Candidate seed #938174
```

That candidate deterministically produces:

```text
Master key
    ↓
child private key
    ↓
public key
    ↓
Bitcoin address
```

Maybe the result is:

```text
bc1qABC...
```

The attacker asks:

> Has `bc1qABC...` ever appeared on the blockchain?

If no:

```text
Candidate rejected.
```

Try the next one.

Then eventually:

```text
Candidate seed #2849182
       ↓
derived address:
bc1qXYZ...
       ↓
BLOCKCHAIN:
2.73 BTC
```

Now things get extremely interesting.

Because if that candidate seed generates an address known to belong to a funded wallet, the attacker has effectively found the secret necessary to control it.

Block calls public wallet information a **candidate-validation oracle** for exactly this reason. 

---

## Attack Flow

The whole attack now looks like this:

```text
             BUGGY COLDCARD RNG
                     │
                     ▼
       smaller candidate universe
                     │
                     ▼
            Candidate RNG state
                     │
                     ▼
               Candidate seed
                     │
                     ▼
             Candidate private key
                     │
                     ▼
              Candidate address
                     │
                     ▼
           ┌───────────────────┐
           │ Public blockchain │
           └─────────┬─────────┘
                     │
              Does it match?
                  /      \
                NO        YES
                │          │
             continue      ▼
                        seed found
                            │
                            ▼
                      control funds
```

Notice what is **not** in that diagram:

```text
Hack user's laptop

Steal seed backup

Plug into COLDCARD

Guess COLDCARD PIN

Break Bitcoin encryption

Intercept USB

Access hardware wallet remotely
```

None of those is fundamentally required if the secret was predictable when it was originally created.

---

## Part 10: So How Do Attackers Know Which Bitcoin Wallets Are COLDCARD Wallets?

This requires another subtle distinction.

Bitcoin does **not** normally publish:

```text
THIS ADDRESS WAS CREATED BY A COLDCARD MK3
SERIAL NUMBER 123456
FIRMWARE 4.1.2
```

An ordinary Bitcoin address does not inherently announce:

> "Hi, I'm vulnerable."

So an attacker isn't necessarily starting with a perfect list of:

```text
All vulnerable COLDCARD owners
```

Instead, the more powerful approach is essentially the reverse:

```text
Generate wallets that
the vulnerable RNG could produce
             ↓
derive their addresses
             ↓
look for those addresses
on the blockchain
```

Think about that difference.

You don't necessarily start with:

> "Find Dan's wallet and crack it."

You can start with:

> "Generate candidate wallets produced by the vulnerable process and see whether any of them correspond to real Bitcoin."

That is much closer to a giant cryptographic scavenger hunt.

And because Bitcoin's ledger is public, the attacker can perform much of the candidate checking without interacting with victims at all. 

---

## Part 11: They're Generating Wallet Addresses?

**Yes.**

But they're not creating new wallets on the Bitcoin network in the way you might initially imagine.

Remember:

```text
Seed
 ↓
private key
 ↓
public key
 ↓
address
```

Those calculations can all happen offline.

You don't "register" a Bitcoin address with Bitcoin.

So an attacker can take:

```text
Candidate Seed A
```

and calculate:

```text
Address A
```

Then:

```text
Candidate Seed B
```

produces:

```text
Address B
```

Then:

```text
Candidate Seed C
```

produces:

```text
Address C
```

And so on.

They can generate enormous numbers of candidate addresses locally.

They're effectively asking:

> **If COLDCARD produced this particular weak RNG output, which Bitcoin addresses would the resulting wallet own?**

Then they compare those addresses to blockchain history.

That's the missing mental model.

---

## Part 12: Why Can't Bitcoin Tell the Difference?

Because from Bitcoin's perspective, the resulting key is still mathematically valid.

Bitcoin sees:

```text
valid private key
        ↓
valid public key
        ↓
valid signature
```

Bitcoin has no way to ask:

> "Was this private key generated using excellent randomness?"

A valid private key generated with terrible randomness is still a valid private key.

It's like a password system.

Suppose my password is:

```text
123456
```

The server doesn't say:

> "You chose that predictably, therefore it is not a password."

It works perfectly.

It's just easy for someone else to discover.

The same principle applies here.

---

## Part 13: This Wasn't Bitcoin Being Cracked

This distinction matters.

Attackers did **not** break:

```text
SHA-256
```

They did not break:

```text
secp256k1
```

They did not discover some magical shortcut for reversing Bitcoin addresses into private keys.

Instead, they attacked something far more mundane:

```text
How was the secret originally chosen?
```

The mathematics protecting Bitcoin can be extraordinarily strong while the system still fails if the private key originates from insufficient randomness.

Think of a bank vault with an incredibly strong lock.

The lock isn't particularly useful if somebody chooses:

```text
Combination: 1-2-3-4
```

---

## Part 14: Why an Air-Gapped Hardware Wallet Didn't Save You

This is probably the most uncomfortable lesson from the vulnerability.

Hardware wallets are designed primarily around protecting secrets after they exist.

Conceptually:

```text
PRIVATE KEY

             Internet
                X
                │
        ┌───────┴────────┐
        │ Hardware Wallet │
        │                 │
        │   PRIVATE KEY   │
        │      stays      │
        │     inside      │
        └─────────────────┘
```

Great.

But suppose the private key was predictable from the beginning.

Then you get:

```text
Attacker
   │
   │ does not steal secret
   │
   ▼
reconstructs same secret independently
```

The private key never has to leave the COLDCARD.

The attacker creates their own copy.

That bypasses the entire point of keeping the original key offline.

---

## An Analogy

Imagine you own a safe.

Your combination never leaves the safe company.

Nobody photographs it.

Nobody intercepts it.

Nobody breaks into your house.

Excellent.

Except the safe company has a bug in its combination generator:

```text
Combination =
house construction year
+
street number
+
minute safe was installed
```

The combination remains secret inside the safe.

But secrecy is irrelevant if somebody can independently reconstruct it.

That's essentially the category of failure we're discussing.

---

## Part 15: The Mk2/Mk3 Case vs. Newer COLDCARDs

This is another area where articles can become misleading.

The impact was not identical across all COLDCARD generations.

---

### Mk2 / Mk3

For affected Mk2/Mk3 firmware, the problematic software RNG path did not receive the cryptographically secure reseeding that later models added.

COLDCARD's current technical assessment estimates an **effective search space around 40 bits** under its stated attack assumptions. 

For perspective:

```text
2^40 ≈ 1.1 trillion
```

That sounds enormous.

But cryptographic security normally deals with numbers vastly beyond human intuition.

Compare:

```text
2^40
≈ 1,099,511,627,776
```

with:

```text
2^128
≈ 340,282,366,920,938,463,463,374,607,431,768,211,456
```

Those are not remotely comparable security levels.

---

## Part 16: Mk4, Q and Mk5 Were Better — But Still Affected

Later devices added randomness from secure elements.

So this wasn't simply:

```text
same exact Mk3 bug
```

with a new case.

There was additional protection.

However, Block found that the secure-element data was hashed and only **four bytes — 32 bits — were passed into the relevant `reseed()` operation**, replacing one state word in Yasmarang. 

COLDCARD's broader attack model currently estimates approximately **72 bits of effective entropy** for affected Mk4, Q, and Mk5 seeds rather than the intended security target. 

---

## Wait — 32 Bits or 72 Bits?

Both figures appear in reporting.

This is where precision matters.

Block's analysis says that **once the fallback RNG state and call history are fixed**, the secure-element reseed creates at most:

```text
2^32
```

securely distinguished output streams.

That is describing the cryptographically secure unknown introduced by that particular reseed operation. 

COLDCARD's approximately:

```text
72 bits
```

figure is a broader estimate of effective attack complexity under its assumptions, including other state an attacker may need to search or constrain. 

So don't read:

```text
32 vs 72
```

as:

> "One of them can't do math."

They're modeling somewhat different pieces of the attack.

And both organizations caution that real-world recovery cost depends on exactly what the attacker knows about a particular device's state and history. 

---

## Part 17: How Serious Is 72 Bits?

Much stronger than 40 bits.

But substantially weaker than the expected security margin.

And this is another reason not to casually say:

> "Oh, attackers just brute-forced 2^72 seeds."

That oversimplifies the actual attack.

The goal is to constrain several variables and exploit structure in the vulnerable generation process.

Think:

```text
all possible Bitcoin seeds
```

versus:

```text
seeds this specific buggy
algorithm could plausibly have
generated under plausible states
```

That's the key distinction.

---

## Part 18: Why Was This So Difficult to Notice?

Because the output looked fine.

Imagine running the device ten times and getting:

```text
7f29ac31...
b19d06ef...
58ad9032...
93c01fe8...
```

Nothing immediately screams:

```text
BROKEN RANDOMNESS
```

A deterministic PRNG can produce numbers that look extremely random statistically.

Block also notes that COLDCARD had a basic health check designed to catch obvious repeated RNG values.

But a deterministic PRNG normally produces different consecutive outputs.

So it can easily pass a test like:

```text
output1 != output2
```

while still being predictable to someone who knows the state. 

This is the difference between:

```text
"Does this output look random?"
```

and:

```text
"Can an adversary predict this output?"
```

The second question is what cryptography actually cares about.

---

## Part 19: Why Open Source Didn't Automatically Save Anyone

COLDCARD's firmware source was publicly available.

Yet the issue survived for years.

That isn't necessarily surprising.

The vulnerable behavior crossed several pieces of software:

```text
COLDCARD code
      ↓
libNgU
      ↓
MicroPython
      ↓
compiler configuration
      ↓
linker/symbol resolution
      ↓
actual runtime function
```

A reviewer could inspect:

```text
the hardware RNG implementation
```

and confirm:

> "Yep. Looks good."

That still doesn't prove that:

```text
New Wallet
```

actually reaches that implementation at runtime.

COLDCARD says prior review verified that the intended hardware RNG code was present, but did not verify the complete end-to-end symbol resolution from wallet generation through the relevant submodules. 

That's an incredibly valuable software-security lesson:

> **Having secure code somewhere in the binary is not the same thing as proving the security-critical operation actually uses it.**

---

## Part 20: The Failure Chain

The vulnerability is easier to understand when we stop treating it as one giant mysterious "RNG bug."

It was a chain.

```text
1. Wallet generation needs entropy
             ↓
2. Code path changed during migration
             ↓
3. New code requested randomness
   through a different abstraction
             ↓
4. Build/configuration logic behaved
   differently than intended
             ↓
5. Wrong RNG implementation became
   reachable
             ↓
6. Deterministic PRNG generated most
   of the relevant randomness
             ↓
7. Later models mixed in additional
   entropy, but insufficiently
             ↓
8. Seed looked completely normal
             ↓
9. Wallet operated completely normally
             ↓
10. Attacker later reconstructs
    candidate RNG outputs
             ↓
11. Derives candidate Bitcoin addresses
             ↓
12. Blockchain validates candidates
             ↓
13. Correct seed gives attacker
    valid signing keys
             ↓
14. Bitcoin accepts the transaction
    because the signature is legitimate
```

That's the attack.

No magic.

Just a catastrophic failure at the foundation.

---

## Part 21: What About Dice Rolls?

This is one of the interesting protections COLDCARD already supported.

Users could contribute their own entropy using physical dice.

Conceptually:

```text
Device randomness
       +
your private dice rolls
       ↓
     hashing
       ↓
   final seed
```

So even if:

```text
Device randomness = weak
```

independent randomness from:

```text
physical dice
```

can restore unpredictability.

According to COLDCARD's current advisory, if the affected **Add Dice Rolls** workflow included at least **50 fair, independent, private dice rolls**, those rolls contributed at least 128 bits of independent entropy. With 99 or more qualifying rolls, COLDCARD says the dice contributed approximately 256 bits. 

The important words are:

**fair, independent, private.**

Typing:

```text
1
1
1
1
1
1
1
...
```

is obviously not entropy.

Neither is using dice rolls that an attacker has recorded.

---

## Part 22: What About a BIP-39 Passphrase?

This is different from the COLDCARD PIN.

Your seed might be:

```text
24 words
```

Then you can add a BIP-39 passphrase:

```text
24 words
      +
secret passphrase
      ↓
different wallet
```

Every different passphrase generates a different wallet.

So if your underlying seed is weak but the attacker doesn't know a strong, independently chosen passphrase, they have another secret to overcome.

COLDCARD's current guidance says a **strong, unique BIP-39 passphrase** creates an additional barrier, but explicitly warns that it does **not repair the compromised seed itself**. Users with affected seeds are still instructed to migrate. 

And:

```text
COLDCARD PIN
```

is **not** the same thing as:

```text
BIP-39 passphrase
```

The PIN protects access to the device.

The BIP-39 passphrase changes the wallet cryptographically.

---

## Part 23: Does Updating the Firmware Fix My Wallet?

**No.**

This may be the single most important practical takeaway.

Suppose vulnerable firmware generated:

```text
OLD SEED
```

Then you install fixed firmware.

You now have:

```text
Fixed firmware
+
OLD SEED
```

The seed hasn't magically changed.

Its original randomness is whatever it was when it was created.

The current COLDCARD security status explicitly says the fixed firmware corrects **future seed generation** but does not repair existing affected seeds. 

To fix the underlying problem, you need:

```text
Fixed RNG implementation
        ↓
brand-new randomness
        ↓
brand-new seed
        ↓
brand-new wallet
        ↓
move Bitcoin
```

---

## Part 24: Moving the Same Seed to Another Hardware Wallet Doesn't Fix It Either

Suppose you generated the vulnerable seed on a COLDCARD.

Then imported those words into:

```text
Trezor
```

or:

```text
Ledger
```

or:

```text
Sparrow
```

or another device.

You haven't changed:

```text
THE SEED
```

You've only changed where it is stored.

Block specifically calls this out: an affected seed remains affected after export or migration to another wallet because the weakness belongs to the original seed itself. 

Think:

```text
Weak password:

password123
```

Moving it from:

```text
Laptop A
```

to:

```text
Laptop B
```

doesn't turn it into a stronger password.

---

## Part 25: What Is Currently Considered Affected?

As of **August 15, 2026**, COLDCARD's current security status lists the following minimum fixed releases. 

| Device / track | Affected seed generation | Minimum fixed firmware |
|---|---|---|
| Mk2 / Mk3 | 4.0.1 through 4.1.9 | **4.2.0+** |
| Mk4 / Mk5 Standard | Before 5.6.0 | **5.6.0+** |
| Q Standard | Before 1.5.0Q | **1.5.0Q+** |
| Mk4 / Mk5 Edge | Before 6.6.0X | **6.6.0X+** |
| Q Edge | Before 6.6.0QX | **6.6.0QX+** |

TAPSIGNER, OPENDIME, and SATSCARD use different codebases and are not listed as affected by this issue. 

Most importantly:

> **What matters is the firmware that generated the seed — not simply which firmware is installed today.**

---

## Part 26: The Practical Decision Tree

```text
Did COLDCARD itself generate the seed?
             │
        ┌────┴────┐
       NO         YES
       │           │
Imported seed      ▼
isn't weakened   Was it generated
merely because   on affected firmware?
COLDCARD held it      │
                  ┌───┴───┐
                 NO      YES
                 │         │
              Not this     ▼
               issue    Did you add
                        >= 50 fair,
                        independent,
                        PRIVATE dice
                        rolls during
                        generation?
                         │
                    ┌────┴────┐
                   YES        NO /
                    │        unsure
                    ▼          │
             Dice exception    ▼
             may apply       MIGRATE
```

A strong BIP-39 passphrase may add substantial protection, but COLDCARD's current guidance still says an affected underlying seed should ultimately be replaced. 

---

## Part 27: Was This Actually Exploited?

This was not merely a lab curiosity.

Block published its analysis on **July 30, 2026**, explicitly saying that active exploitation was underway following reports from COLDCARD users. 

Bitcoin Optech reported the following day that users had discovered unauthorized transactions from COLDCARD-generated wallets and that estimated losses had already exceeded **1,000 BTC** at the time of publication. 

Later blockchain analysis from TRM Labs attributed multiple theft waves totaling roughly **1,816 BTC**, valued around $116 million at the time of its August 5 report. Because attribution and on-chain clustering can evolve, that figure is better understood as an analyst estimate rather than an immutable final total. 

The vulnerability therefore crossed the important line from:

```text
"Someone could theoretically do this."
```

to:

```text
"Real funds appear to have been stolen
while researchers were investigating it."
```

---

## Part 28: Why This Vulnerability Is So Interesting

Most people imagine hardware-wallet attacks like this:

```text
Malware
   ↓
computer
   ↓
USB
   ↓
hardware wallet
   ↓
steal private key
```

This was fundamentally different.

The attack is closer to:

```text
Study wallet-generation algorithm
              ↓
discover entropy weakness
              ↓
reconstruct possible wallets
              ↓
search public blockchain
              ↓
find funded matches
```

The attacker may never interact with the victim.

May never see the hardware wallet.

May never see the seed phrase.

May never compromise the victim's computer.

May never know the PIN.

They can independently arrive at the same secret.

That is what makes RNG failures so dangerous.

---

## Part 29: A Cybersecurity Analogy

Imagine an application generates API keys.

They're supposed to look like:

```text
7Fr12zRqx7aP9bT8N6L...
```

The developer assumes:

```text
128 bits of randomness
```

But someone discovers the keys are actually generated from:

```text
username
+
current timestamp
+
process ID
```

Then hashed:

```text
SHA256(
    username
    + timestamp
    + process_id
)
```

The resulting API token looks gorgeous:

```text
9cc5a0f3e41b78...
```

Long.

Hexadecimal.

SHA-256.

Very cyber.

But an attacker who knows:

```text
username = dan

account created approximately:
3:00–3:05 PM

possible process IDs:
1–65535
```

doesn't attack SHA-256.

They generate every plausible input:

```text
dan + 3:00:00 + PID1
dan + 3:00:00 + PID2
dan + 3:00:00 + PID3
...
```

hash each one and test the resulting tokens.

The cryptographic hash function is perfectly secure.

The input entropy was the problem.

That's essentially the category of failure here.

---

## Part 30: Another Way to Think About It

You can reduce the entire vulnerability to one sentence:

> **A cryptographic secret is only as unpredictable as the process that created it.**

Everything downstream can be perfect.

```text
Excellent hardware security
        ↓
air gap
        ↓
encrypted backup
        ↓
PIN protection
        ↓
tamper resistance
        ↓
secure transaction signing
```

But if the first step was:

```text
Generate predictable secret
```

then:

```text
                 ┌────────────────────┐
                 │ Predictable secret │
                 └──────────┬─────────┘
                            │
                everything below it
                inherits the problem
                            │
          ┌─────────────────┼─────────────────┐
          ▼                 ▼                 ▼
     private keys       public keys      addresses
          │
          ▼
     signatures
```

You can't bolt unpredictability onto an already-predictable private key afterward.

---

## The Big Misconceptions

### "Attackers guessed all possible 24-word phrases."

**No.**

They exploited structure in how affected devices generated the underlying randomness.

---

### "They reversed Bitcoin addresses into private keys."

**No.**

They generated candidate private keys forward and checked whether the resulting addresses matched real blockchain data.

---

### "They hacked the COLDCARD remotely."

Not necessarily.

The vulnerability lives in the generated secret itself.

---

### "The hardware random-number generator broke."

Not exactly.

The published analysis indicates that the intended hardware RNG existed, but an integration/build issue caused wallet generation to reach the wrong software RNG path. 

---

### "PRNGs are insecure."

No.

Cryptographically secure PRNGs are used everywhere.

The problem was **this generator, this initialization, and this integration path**.

---

### "My seed has 24 words, so it must have 256 bits of security."

No.

Twenty-four BIP-39 words can encode 256 bits of source entropy, but only if those underlying bits were actually chosen with that level of unpredictability. 

---

### "I updated my firmware, so I'm safe."

Newly generated seeds on fixed firmware use the remediated path.

An old affected seed remains old and affected. 

---

### "I moved my seed to another hardware wallet."

Same seed.

Same underlying entropy.

Same problem.

---

### "I had a PIN."

The COLDCARD PIN protects the device.

It doesn't add entropy to the underlying BIP-39 wallet.

---

### "I had a strong BIP-39 passphrase."

That is materially different.

It adds an independent secret an attacker also needs, although COLDCARD still recommends replacing an affected underlying seed. 

---

## The Entire Thing in One Diagram

```text
                 WHAT SHOULD HAVE HAPPENED

              Physical hardware entropy
                         │
                         ▼
                       TRNG
                         │
                         ▼
               unpredictable entropy
                         │
                         ▼
                  BIP-39 mnemonic
                         │
                         ▼
                    master key
                         │
                         ▼
                 Bitcoin addresses


===============================================================


                  WHAT WENT WRONG

           device/timing-related state
                        +
           software Yasmarang PRNG
                        +
        limited additional secure entropy
              on later devices
                        │
                        ▼
             random-looking output
                        │
                        ▼
                BIP-39 mnemonic
                        │
                        ▼
                   master key
                        │
                        ▼
                Bitcoin addresses
                        │
                        ▼
               Public blockchain
                        ▲
                        │
                        │
                ATTACKER DOES:
                        │
       recreate plausible RNG conditions
                        │
                        ▼
                 candidate seed
                        │
                        ▼
               candidate address
                        │
                        ▼
           compare against blockchain
                        │
                   ┌────┴────┐
                   │         │
                 match     no match
                   │         │
                   ▼         └──► next candidate
              seed recovered
                   │
                   ▼
                Bitcoin
                 stolen
```

---

## The Bigger Lesson

There's a tendency in security to focus on impressive cryptography:

```text
AES-256
SHA-256
secp256k1
Secure Elements
HSMs
air gaps
```

But many catastrophic failures happen in the glue between those technologies.

Configuration.

Build systems.

Random-number generation.

Key initialization.

Library integration.

State handling.

Fallback behavior.

Error handling.

The COLDCARD incident is almost a perfect example.

The interesting question isn't:

> **"Was Bitcoin's cryptography broken?"**

It wasn't.

The interesting question is:

> **"Did the system actually provide strong randomness to the code that created the secret?"**

For affected firmware, the answer was not what everyone thought it was. 

---

## Final Cheat Sheet

| Concept | Simple explanation |
|---|---|
| **RNG** | Something that generates random numbers |
| **TRNG** | Gets randomness from physical hardware behavior |
| **PRNG** | Algorithm that generates random-looking values from internal state |
| **CSPRNG** | PRNG specifically designed for cryptographic security |
| **Entropy** | How unpredictable something is |
| **Deterministic** | Same state/input → same output |
| **Seed phrase** | Human-readable representation used to recover a wallet |
| **Private key** | Secret allowing Bitcoin to be spent |
| **Public key/address** | Information derived from the private key that can safely be public |
| **COLDCARD bug** | Wallet generation reached an unintended deterministic software RNG path |
| **Attacker strategy** | Recreate plausible RNG outputs rather than randomly guessing every BIP-39 phrase |
| **Validation** | Derive addresses from candidate seeds and compare them with public Bitcoin data |
| **Why air gap failed** | Attacker reconstructs the secret instead of extracting it |
| **Firmware update** | Protects future seed generation; does not repair an existing weak seed |
| **New device + same seed** | Still vulnerable |
| **Independent dice entropy** | Can provide randomness independent of the affected RNG |
| **BIP-39 passphrase** | Adds an additional secret and produces a different wallet |
| **COLDCARD PIN** | Protects device access; not equivalent to a BIP-39 passphrase |

---

## If You Remember Only Five Things

**1. Your seed phrase isn't secure because it contains 24 words.**

It's secure because the information encoded by those words is supposed to have been chosen unpredictably.

**2. The attacker isn't randomly guessing the entire universe of Bitcoin seeds.**

The vulnerability provides structure that can dramatically narrow the candidate space.

**3. Bitcoin's public blockchain helps verify candidates.**

Candidate seed → candidate address → check blockchain.

**4. An air-gapped wallet can't protect you from a secret that another person can independently reconstruct.**

The secret never has to physically leave the wallet.

**5. Fixing the RNG does not fix old RNG output.**

Affected wallets require a **newly generated seed** and migration, not merely a firmware update. 

---

## Sources & Further Reading

The primary technical source for the vulnerability mechanics is [Block Bitcoin Engineering and Security's July 30, 2026 analysis](https://engineering.block.xyz/blog/predictable-rng-fallback-and-32-bit-reseed-in-coldcard-firmware), which traces the incorrect RNG integration, deterministic Yasmarang fallback, affected generations, limited 32-bit reseeding on later devices, and candidate-validation attack model. 

[Coinkite/COLDCARD's technical backgrounder and security advisory](https://blog.coinkite.com/coldcard-mk3-seed-generation-warning/) provide the manufacturer's explanation of the integration failure, its approximately 40-bit and 72-bit attack-complexity estimates, affected firmware, dice-entropy exception, passphrase guidance, and remediation. 

The [current COLDCARD Security Status](https://coldcard.com/security), verified August 15, 2026, contains the latest fixed-release matrix and explicitly distinguishes firmware remediation from seed migration. 

The [COLDCARD migration guide](https://coldcard.com/security/migrate) describes how imported seeds, dice-generated entropy, passphrases, and affected on-device seeds should be treated. 

The official [BIP-39 specification](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) explains the relationship between initial entropy, checksums, and mnemonic length. 

For independent contemporary reporting on the incident, [Bitcoin Optech](https://bitcoinops.org/en/newsletters/2026/07/31/) documented active wallet theft and early loss estimates, while [TRM Labs](https://www.trmlabs.com/resources/blog/the-largest-hardware-wallet-exploit-of-2026-inside-the-usd-116-million-coldcard-hack) later published blockchain analysis covering multiple theft waves. 
