# Coldcard firmware: reproducible builds and the seed entropy advisory

> The Coldcard firmware repository publishes the device firmware and a desktop simulator, and it lets you rebuild the exact bytes shipped on your device. It also carries a security advisory saying seeds generated between 2021 and July 2026 came from poor entropy, which makes the repository a read-first document for anyone holding funds on this wallet.

**Coldcard/firmware** — ❄️ Firmware and simulator for Coldcard Hardware Wallet

- Repository: https://github.com/Coldcard/firmware
- Website: http://coldcard.com
- Stars: 781 · Forks: 231
- Language: Python
- License: NOASSERTION
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/coldcard-firmware

## The advisory that dominates the repository

The first thing in the README is a security advisory, not a description of the firmware, and that placement is deliberate.

The advisory states that versions from 2021 to July 2026 had a bug which produced poor entropy. Any secrets generated on a COLDCARD in that period should be regenerated and funds moved on chain immediately. That is an unusually blunt instruction, and it is worth being precise about what it means: this is not a warning about a weakness in the wallet's key storage or its signing logic, it is a statement that the randomness fed into seed generation may have been predictable. A seed with poor entropy is a compromised seed no matter how sound the rest of the device is.

The advisory also says master seeds can only be trusted from certain releases, and lists the levels: 5.6.0 for Mk4 and Mk5, 1.5.0Q for Q1, 4.2.0 for Mk3, and 6.6.0 for Edge Mk and Q. The linked blog posts give updates and technical background on the bug.

For a developer, the important consequence is that the repository is not only a code drop. It is the place where the maintainers document which historical firmware can still be relied upon, which matters when you are auditing a device you already own.

## Passphrases and dice as partial mitigation

The advisory offers two partial mitigations, and it is careful to say partial.

The first is a BIP-39 passphrase, which mitigates some of the risk because it relies on the entropy your passphrase adds. That is the key phrase: the passphrase contributes additional entropy, so a weak seed plus a strong passphrase is stronger than a weak seed alone. It does not repair the original entropy.

The second is dice rolls introduced into the secret, which the advisory says provide 2.5 bits of entropy per roll. Two and a half bits per roll is a useful number for calibrating expectations, since it means that a handful of rolls adds a small but real amount of entropy compared with the much larger space a machine generator was supposed to supply.

Neither mitigation makes an affected seed safe to keep. The instruction to regenerate and move funds remains the operative one, and moving funds is the part people tend to postpone, because an affected seed still works and still signs. A key that can sign and should not be trusted is the worst kind of state to sit in.

For anyone building tooling around this wallet, the practical consequence is that seed generation history has to be modelled explicitly, with per-device and per-release dates, which is exactly the kind of rule a firmware repository is a reasonable place to publish.

## Rebuilding the exact bytes on your device

The reproducible build story is the strongest technical claim in the README. The goal is to have confidence that the source tree is the same as the binary on your device, and the process is automated with Docker so that the rebuild produces exactly the same bytes.

The steps are: install Docker and start it, install make if you do not have it, then check out a specific version and build. The concrete example given is:

```shell
git clone https://github.com/Coldcard/firmware.git
cd firmware
# DOWNLOAD https://coldcard.com/downloads
# get a copy of binary into ./releases/2026-03-05T2052-v5.5.0-mk-coldcard.dfu
git checkout 2026-03-05T2052-v5.5.0
cd stm32
make -f MK4-Makefile repro
```

Note the shape of this. You download the released binary from the vendor, drop it into the releases directory, check out the matching source version, and ask the build to compare. At the end the process prints either a clear confirmation message or the differences. Build products land in firmware/stm32/built.

If you do not trust the result of make repro, the README points to docs/notes-on-repro.md, which breaks the process down. That is the right place to look, because a reproducibility claim is only as good as the explanation of how to check it.

For Q firmware the process is the same with one substitution: change MK4-Makefile in the last step to Q1-Makefile.

## master, edge and the legacy branch for Mk3 and older

The repository maintains two long-lived branches, master and edge. The README explains the split: edge contains features that may not be ready for prime time, such as Taproot or Miniscript, and the standards for releasing new edge versions are lower so the project can iterate faster and get these advancements out to other developers.

That is a reasonable trade for a hardware vendor whose release train is gated by certification, and it is worth noticing that it also means edge is where you look for the newest protocol work rather than the newest release for your device.

The hardware support is organised by shared code. Q and Mk series share the same code base, and the individual files that differ can be seen in the differences between shared/manifest_mk4.py and shared/manifest_q1.py, with common files listed in shared/manifest.py. Firmware built for Mk5 supports the Mk4 without any functional differences, which is the sort of statement that matters when you are deciding which device to buy.

There is also a v4-legacy branch, which holds firmware supporting only Mk3, Mk2 and earlier. The master branch, the default, covers the latest hardware, the Mk and Q lines.

The releases directory carries the change log at releases/ChangeLog.md and a PGP signature file at releases/signatures.txt, and the binaries themselves are published separately through the downloads page.

## Running the desktop simulator on macOS

The repository includes a simulator so the firmware can be run and tested on a desktop without a device. The macOS path is the one documented in most detail, and it has real friction points.

The requirements are Python 3.5 or higher and Homebrew. On an ARM-based Mac, the README suggests creating a new shell with arch -x86_64 bash before starting or continuing work on the tree, which tells you the simulator build is still aimed at an Intel toolchain.

The packages to install are:

```shell
brew install sdl2 xterm swig
brew install --cask xquartz gcc-arm-embedded
```

The arm toolchain itself comes from a tap, and the README notes you may need to upgrade gcc-arm-embedded because version 10.2 or higher is required.

The build sequence creates a virtualenv, installs the requirements, and works around a specific compiler problem in the bundled MicroPython by setting MPY_CFLAGS before building the cross compiler and the simulator:

```shell
brew install automake autogen virtualenv
virtualenv -p python3 ENV
source ENV/bin/activate (or source ENV/bin/activate.csh based on shell preference)
pip install -U pip
pip install -r requirements.txt
```

The comment in the README calls this a workaround for warnings in bundled MicroPython under current Apple Clang, and the same flag list is then passed to make -C external/micropython/mpy-cross, to make setup in the unix directory, and to the make in unix itself, before running ./simulator.py. You may need to reboot to avoid a DISPLAY is not set error, and afterwards the simulator starts with a single source and cd command.

## The Linux simulator setup and flashing a rebuilt firmware

Linux has a shorter path, described as all the steps needed to install and run the simulator on Ubuntu 20.04. The system requirements are a single long apt install:

```shell
apt install build-essential git python3 python3-pip libudev-dev gcc-arm-none-eabi libffi-dev xterm swig libpcsclite-dev python-is-python3 autoconf libtool python3-venv
```

The clone is recursive there too, and the README warns that getting the sources takes a long time because of the external libraries.

Building and installing the actual firmware is a short sequence. The command line tool is installed from the cli directory in editable mode, and the firmware is built and signed from the stm32 directory:

```shell
cd ../cli; pip install --editable .
cd ../stm32; make setup && make; make firmware-signed.dfu
```

The resulting firmware-signed.dfu can be loaded onto a Coldcard with the ckcc tool, which was installed by the previous step:

```shell
ckcc upgrade firmware-signed.dfu
```

The README shows the expected output of that upload, with a byte count and a progress bar.

Two practical warnings from the setup section are worth repeating. The clone must be recursive to get the submodules, and the checkout must not live in a path containing spaces, because the Makefiles do not handle that and the project is not planning to fix it. If a checkout is already in a broken state, git fetch followed by git reset --hard origin/master is the documented recovery.

## Where the build depends on Python and several sub-trees

The requirements file shows how many separate pieces have to agree, and it is worth reading before you start.

The top level lists namedlist and pyusb as the desktop Python modules required to build the firmware binaries, and then pulls in five further requirement files: cli, external/ckcc-protocol, testing, unix and misc/gpu. It also lists ckcc-protocol with the cli extra. So a build is not a single environment with two packages in it, it is the union of six environments, which is why the README says Python requirements may change between versions and tells you to run pip install -r requirements.txt at the top level.

The repository layout mirrors that structure. The top level contains cli for the command line tools, stm32 for the firmware build, unix for the simulator, shared for the code shared between device families, hardware for board definitions, graphics, external for the third-party libraries including MicroPython and ckcc-protocol, testing for the test harness, releases for the change log and signatures, docs, misc and requirements.txt. The .gitmodules file is what makes the recursive clone necessary.

Licensing is worth a note as well. The repository is published with a LICENSE file that GitHub cannot classify, and there is a separate COPYING-CC file in the tree, so the licensing terms are not simply a single well-known identifier. Read both files before you redistribute code from this tree.

## Conclusion

Use this repository if you run a Coldcard Mk, Q or Edge device and want to verify that the firmware on it matches the published source, or if you need the desktop simulator for development against the real firmware code. Do not treat it as a wallet recovery tool: if your device generated a seed between 2021 and July 2026, the advisory says to regenerate it and move funds on chain immediately, and no amount of firmware review changes that. Before you build, check your device model against the list of firmware levels whose master seeds can be trusted, install the Python requirements from requirements.txt, and clone without --recursive only if you are not doing a full build, since the recursive clone is what pulls in the external libraries.

## FAQ

### What is the Coldcard firmware repository used for?

It holds the firmware and the desktop simulator for the Coldcard Bitcoin hardware wallet, and it lets you rebuild the exact binary that runs on your device through a reproducible build process automated with Docker.

### Which Coldcard firmware versions are affected by the poor entropy bug?

The security advisory in the README says versions from 2021 to July 2026 had a bug which produced poor entropy, and that secrets generated on a device in that period should be regenerated with funds moved on chain immediately.

### How do I verify that the firmware on my Coldcard matches the source?

Download the released binary, check out the matching source version, and run make -f MK4-Makefile repro in the stm32 directory, using Q1-Makefile for Q firmware. The build prints either a confirmation or the differences, and docs/notes-on-repro.md explains the process in detail.

### How do I build the Coldcard firmware and flash it to the device?

Install the command line tool with cd ../cli and pip install --editable ., then from the stm32 directory run make setup && make followed by make firmware-signed.dfu. The resulting firmware-signed.dfu is loaded onto the device with ckcc upgrade firmware-signed.dfu.

### What is the difference between the master and edge branches?

Both are long-lived branches, and edge holds features that may not be ready for prime time, such as Taproot or Miniscript, with lower release standards so the project can iterate faster. Firmware for Mk3, Mk2 and earlier lives on the v4-legacy branch.

## Sources

- [Coldcard/firmware on GitHub](https://github.com/Coldcard/firmware)
- [Issues](https://github.com/Coldcard/firmware/issues)
- [Project website](http://coldcard.com)
- [README](https://github.com/Coldcard/firmware/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/coldcard-firmware
