bugfix: guard low-level master secret writes
What changed, and why it matters
This commit adds safety checks to prevent the COLDCARD wallet from overwriting or restoring the main master secret while a temporary seed is active. Without these guards, a low-level restore or seed-setting operation could potentially replace the real wallet seed while the device is operating under a temporary seed, leading to confusion or loss of funds. The fix adds explicit assertions that block these operations when a temporary seed is in use.
Review whether any other low-level seed-write or restore entry points also need similar guards, and verify that the assertion failures are handled gracefully in the UI rather than crashing the device. Consider adding tests that exercise temporary-seed scenarios against these functions.
Security signals we found
New assertion guards added to master-secret write paths
Prevents low-level restore/seed-set while temporary seed is active
Protects persistent seed from being overwritten during temporary-seed session
Defensive-in-depth fix in backup restoration and seed storage code
Evidence from the diff
Two functions in the COLDCARD firmware—restore_from_dict_ll() in shared/backups.py and set_seed_value() in shared/seed.py—now assert that pa.tmp_value is false before proceeding. pa.tmp_value indicates a temporary seed is active. These functions write or restore the master secret into the secure element, and the new guards ensure they cannot be invoked while the device is operating under a temporary seed, preventing accidental or malicious overwrite of the persistent master seed.
Changed components
shared/backups.py: restore_from_dict_ll()shared/seed.py: set_seed_value()Inspect captured patch +4 / −0
### shared/backups.py
@@ -143,6 +143,8 @@ def restore_from_dict_ll(vals, raw):
# - low-level version, factored out for better testing
from glob import dis
+ assert not pa.tmp_value, "temporary seed active"
+
need_ftux = False
#print("Restoring from: %r" % vals)
### shared/seed.py
@@ -977,6 +977,8 @@ def xprv_to_encoded_secret(xprv):
def set_seed_value(words=None, encoded=None, chain=None):
# Save the seed words (or other encoded private key) into secure element.
# BIP-39 passphrase is not set at this point (empty string).
+ assert not pa.tmp_value, "temporary seed active"
+
if words:
nv = seed_words_to_encoded_secret(words)
else:Why this scored 63/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.