more eyes

Which Code Actually Runs?

Questions to ask when software has more than one way to do a job

This note describes kinds of fallback. It reads two public records as examples.

Document which-code-actually-runs.md
Version 0.3 — peer review draft
Audience People who rely on a wallet, a signing device, or a library to make or use keys: read Start here. Technical reviewers: read the full note.
Method Identify each place where software chooses between two ways to do the same job. For each, record what decides the choice, when, and what a reader could inspect to learn which way ran. Tie each statement to a public source.
Changes See the changelog.
Scope Fallbacks in software that makes or uses keys: random sources, cryptographic implementations, and the code that selects between them. Two public records are read. This is not an incident survey, a finding about any organization or person, or an assessment of the security of any product.

Contents

Start here

This section is for anyone who relies on software to make or protect keys. You do not need to read code to use it. The rest of the note is the record behind each question.

What a fallback is. Software often has two ways to do one job. The first way is the one its makers intend. The second way is a backup, called a fallback. The fallback takes over when the first way is not available. A fallback usually exists for a good reason. It lets the software work on an older machine, or on a device that lacks a part.

Why it matters. The two ways can differ in strength. If the backup takes over and nothing tells you, the software still works. It looks the same. You have no sign that the weaker way is in use.

The questions that matter. Ask these about any software that makes or uses keys.

  1. Does the software have more than one way to do this job? Ask for the list. Random numbers and signing are the two jobs to ask about first. See §2.
  2. What decides which way runs? A setting chosen when the software was built can decide it. A check made when the software starts can decide it. Ask which. See §2.
  3. Would anyone know if the backup took over? Ask whether the software stops, warns, or carries on. See §3.
  4. How does the backup differ? A backup can be slower and equally strong. It can also be weaker. Ask what the makers say about it. See §4.
  5. What shows which way ran in the copy you have? A document that describes the intended way is not that evidence. See §5.

How to judge an answer. A good answer shows you something you can check. Examples are a test that fails when the intended part is missing, or a check that the backup is absent from the finished product. A weak answer repeats the claim in different words. A weak answer does not prove a problem. It shows that the claim is not proved yet.

What this note does not do. It does not say that any product is safe or unsafe. It does not say that fallbacks are wrong. It helps you ask which code runs.

1. What the note establishes

A claim about a fallback needs a defined object: a function, a build of a program, or an installed copy. “It uses the hardware random source” and “it uses the native library” are claims about what runs. Neither follows from the presence of that code in a source tree or in a binary.

The other notes in this repository stop one step earlier. The release note asks what a published file is evidence of. The custody note lists four levels of build evidence and ends with “evidence that the device runs that binary.” This note asks a further question inside one binary or one package: of the alternatives it contains, which one executes. See What Can You Check About a Software Release? §2 and Who Can Move Your Bitcoin? §3.

The release note’s three checks tie a file to its source and to the keys that vouch for it. None of them shows which path inside the file runs. A reproducible build shows that a binary matches its source. If the source and the build configuration select the fallback, every honest rebuild contains the same fallback, and matching hashes confirm that the fallback was built as written. A signature and a provenance record carry the same limit: each is a statement about the file, not about the path taken inside it. §3.3 applies the checks to both records.

This note uses public statements and public source. No device was tested, and no build was reproduced.

1.1 Evidence

Each record in §3 has: claim; object and date; public source; what was read; result; unresolved. A statement by a maker about its own product is recorded as the maker’s statement. An analysis by another party is recorded as that party’s statement.

1.2 Terms

Term Meaning here
Fallback A second way to do a job, used when the intended way is not available.
Intended path The way the makers mean the software to use.
Selection The step that decides which way runs.
Build-time selection Selection made when the software is compiled or linked. Every copy of that build then uses the same way.
Run-time selection Selection made when the software starts or when a function is called. Two copies of one file can use different ways. The selection can depend on the environment: one machine has the native library and uses it, and another machine lacks the library and uses the fallback, with the same file on both.
Silent The software gives no error, warning, or record when the fallback is chosen. A fallback can be described in a document and still be silent when it runs.
Fail closed The software stops when the intended way is not available.
Presence and reachability Presence: the intended code is in the file. Reachability: the job in question actually calls it. Presence does not establish reachability.
Parity Two ways return the same results for the same inputs. Parity is about results. It does not cover timing behavior or the quality of random values.

2. Kinds of fallback

Kind When selection happens What decides What a reader could inspect
A random source chosen at build time Compile or link A configuration value, and which function a name resolves to at link time The build configuration, the linked symbols, and a build check that fails on the wrong binding
A cryptographic implementation chosen at import Program start Whether a native library loads The selection code, and whether a failed load raises an error
A per-function mix Program start, per function Whether the loaded library exports each function The table of optional functions, and a way to list which implementation serves each
A substitute written for one platform Compile The build target The source for that target, and the tests that run on it

Three properties apply to every kind.

3. Public records

3.1 Coldcard firmware: the random source for seeds

Claim. In affected firmware releases, seed generation drew on a software generator in place of the device’s hardware random source. The cause was a build-time selection that took the fallback while the build succeeded.

Object and date. The maker’s security advisory and technical account, both first published 30 July 2026, and an independent analysis published the same day. All three were read on 9 October 2026.

Public source. The maker’s advisory and technical account on its blog. An analysis on an engineering blog by another company’s Bitcoin engineering and security team.

What was read. The affected versions. The stated cause. The stated effect on seed strength. The stated fix. The maker’s statement on why earlier review did not find the fault.

Result. Each point below reports what the accounts state, and names the account. This note verified none of those statements: it did not read the firmware source for the fault, test a device, or check an entropy figure. The two points on release evidence are the exception. This note read those in the firmware repository.

Unresolved. The release evidence was sampled at five affected tags, not at every affected release, and the later hardware models’ separate release tracks were not sampled. The note checked that the rebuild step and the signed hash file are present at each tag. It did not run the rebuild, and it did not verify a signature. It found no published rebuild report for an affected release, so the rebuilt check rests on a documented step and not on a second builder’s report. This note did not read the firmware source for the fault itself. The entropy figures are the maker’s preliminary estimates, and the independent analysis gives different bounds under its own conditions. The maker’s account says its investigation continues. Both accounts were read through a page reader, so the quotes need a check against the pages.

3.2 embit: the secp256k1 implementation

Claim. The embit library holds native bindings and a pure-Python implementation of its secp256k1 operations. The library selects between them at import. The full record is in What Can You Check About an embit Release? §3.5.

Object and date. The source tree at tag v0.8.2 and the other sources listed in that record, read 9 October 2026.

Result. The points below summarize that record. The sources and the unresolved items are listed there.

Unresolved. As listed in the embit note. This note adds no reading of its own.

3.3 The release checks, applied to both records

The checks are those of What Can You Check About a Software Release? §2, and the provenance record of its §5. Each cell states what the public record offers for that check. The last column states what the check leaves open for a fallback.

Check Coldcard firmware embit What the check leaves open
Public The firmware source is published. Both accounts trace the fault in that source. The source history is public (embit note §4). Whether anyone traced the call from the job to the intended code. Public source makes that trace possible. It does not show that the trace was done.
Signed The repository publishes PGP-signed hashes of the firmware files, with an entry for the version at each of five sampled affected tags. A signed commit for 0.8.0 and signed tags for later versions. No signature on a release file (embit note §4). A signature vouches for a file. The file can hold the fallback, or both ways.
Rebuilt The repository documents a rebuild that yields “exactly the same bytes,” at each of five sampled affected tags. No second builder’s report for an affected release was found. No second builder’s report was found (embit note §4). A matching rebuild shows that the binary matches the source. A fallback selected by the source and the build configuration is reproduced with it.
Provenance Not read for this note. Attestation steps exist in the release workflow. No completed run was found (embit note §3.3). A provenance record states how a platform built a file. It does not state which path the file takes when it runs.

Three points follow from the table.

The release checks answer “is this file what its source says?” The question in this note is “what does the source, as built, actually do for this job?” Both questions need an answer, and neither answer supplies the other.

4. What separates the two records

The two records share a pattern: a fallback took over, or can take over, with no signal. They differ in every other respect that a reviewer needs. Do not carry a conclusion from one record to the other.

Question Coldcard firmware seed generation embit secp256k1
What job has a fallback? Producing random values for a new seed Elliptic-curve operations, including signing
When is selection made? At build time. Every device with an affected release used the same path. At import. The result depends on the machine: a copy on a machine with a usable native library uses it, and an identical copy on a machine without one uses the pure-Python implementation.
Was the fallback meant to be reachable? No, by the maker’s account. The configuration was meant to exclude it. Yes. The project’s README describes it.
What does the fallback weaken? The unpredictability of the seed, by the maker’s account Not established by the records read. The origin file warns about side channels and key protection. The project’s open change cites differing results.
Who could make use of the difference? Anyone, offline, by the maker’s account Not established by the records read
Is the effect permanent? Yes for an affected seed. A firmware update does not change a seed already made. Not established. The implementation in use can change when the environment changes.
What is the fail-closed form? A build check, in the fixed releases An import that raises an error, in an open change

The first record is an incident with a stated effect. The second is a design property with no reported incident in the records read. The pattern is the same. The consequence is established for one and not for the other.

5. What a project can show

Each control below is paired with the artifact that would let a reader check it. A control without an artifact is a description of intent.

Control What it does Artifact a reader can check
Remove the fallback Leaves one way to do the job The source tree, and a check of the built file for the removed code
Fail closed at build time Stops the build when the intended function is not the one linked The build check, and a record of it failing on a wrong configuration
Fail closed at start Stops the program when the intended library does not load The selection code, and a test that runs without the library and expects an error
Report the selection Lets a caller ask which implementation is active The function that reports it, and its use in a downstream check
Test reachability Shows that the job calls the intended code, not only that the code is present A test that traces the call from the job to the intended function
Check the product Confirms the selection in the finished image A downstream script that inspects the built image

6. Questions that make a claim reviewable

If the claim is Request
It uses the hardware random source Show the build configuration and the function that seed generation calls. Show a check that fails when another function is linked.
The secure code is in the binary Show that the job in question reaches it. Presence is not reachability.
It uses the native library Show what happens when the library does not load: an error, a warning, or a silent change of implementation.
The fallback is only for other platforms Show what excludes it from this build, and a check that the exclusion took effect.
The fallback gives the same results State which results were compared. Parity of results does not cover timing behavior or random values.
The tests pass State whether any test fails when the fallback is in use. A test that passes on both ways does not show which one ran.
The build is reproducible, so the code is verified State what was verified. A matching rebuild shows that the binary matches the source. Ask what shows that the source selects the intended path.
The release is signed and attested State what the signature or attestation covers. Each covers a file. Ask what shows which path the file takes for this job.
It was reviewed State whether the review traced the call from the job to the code, and on which build.
It is fixed State what the fix changes for material made before it. A fix to selection does not change keys already generated.

7. Limits and source use

8. References

Each source is listed once with the date consulted and the sections that cite it. Repository files are pinned to a commit. The other pages are not pinned to a version; each was read on 9 October 2026.

Reference What it defines Cited in
COLDCARD Security Advisory The maker’s advisory: affected versions, stated effect, and guidance. First published 30 July 2026. §3.1, §4
Technical Deep Dive into the Entropy Issue The maker’s account of the cause, the fix, and the earlier review. First published 30 July 2026. §3.1, §4, §5
Predictable RNG fallback and 32-bit reseed in COLDCARD firmware An independent analysis of the configuration, the guard, and the fallback generator. Published 30 July 2026. §3.1
COLDCARD firmware README, commit f28e1b2 The documented reproducible build §3.1, §3.3
COLDCARD firmware commit ee11794 The commit that added the rebuild step, dated 4 March 2021 §3.1
COLDCARD firmware release tags Tags 2021-01-14T1617-v3.2.2, 2021-03-29T1927-v4.0.1, 2021-09-02T1752-v4.1.3, 2022-03-14T1907-v5.0.0, 2023-06-26T1241-v4.1.9, and 2026-03-05T2052-v5.5.0: the README, makefiles, and releases/signatures.txt at each §3.1, §3.3
COLDCARD firmware releases/README.md, commit f28e1b2 The signed hash file for firmware releases §3.1, §3.3
What Can You Check About a Software Release? The three checks and the provenance record §1, §3.3
What Can You Check About an embit Release? §3.5 The embit record and its pinned sources §3.2, §4, §5

Changelog

Newest first. Versioning follows STYLE.md. Version tags use the prefix which-code-v, and each version links to its tagged text. The tags for 0.1 to 0.3 were created on 11 October 2026.

Version Change
0.3 — 9 October 2026 States at the head of the §3.1 result that the points report what the accounts state and that this note verified none of them, except the release evidence it read in the repository. States in §1.2 and §4 that a run-time selection can depend on the environment, so identical copies of one file can use different implementations on different machines.
0.2 — 9 October 2026 Adds §3.3, which applies the release note’s public, signed, rebuilt, and provenance checks to both records and states what each check leaves open for a fallback. States the limit in §1: a reproducible build reproduces a fallback that the source selects. Adds the Coldcard firmware repository’s signed hash file and documented rebuild to §3.1, checked at five affected release tags and at the last tag before the affected range. Adds two §6 rows and a §7 limit.
0.1 — 9 October 2026 First draft. Terms for fallback, selection, and presence versus reachability. Four kinds of fallback. Two public records: Coldcard firmware seed generation, from the maker’s account and one independent analysis, and the embit secp256k1 implementation, summarized from the embit note. A table of what separates the two records, a table of controls with the artifact for each, and a list of reviewable claims.