What changed, and why it matters
This commit fixes a bug in the COLDCARD hardware wallet's WIF (Wallet Import Format) key import feature. Previously, if a user tried to import a file containing the same private key twice, the code could incorrectly count it as a duplicate of an already-saved key rather than as a duplicate within the import file itself. This could cause the import to fail with a misleading 'duplicate WIF(s)' error even when no keys were actually saved yet. The fix properly distinguishes between duplicates inside the import file and duplicates of already-stored keys. There is no direct evidence this is a security vulnerability—it's primarily a usability/robustness fix.
Treat as a routine bugfix. No urgent security action is indicated. If reviewing for a release, verify that the updated test passes and that duplicate handling behaves correctly for edge cases such as mixed duplicate/new keys and empty stores.
Security signals we found
Input validation change for imported cryptographic key material
Logic reordering around duplicate detection
Assertion message tied to duplicate handling
Evidence from the diff
In shared/wif.py, the WIFStore.import_wif() method now checks whether a parsed (pubkey, privkey) tuple already exists in new_wifs (the in-progress import list) before checking against saved keys. The logic is reordered so that: (1) duplicates within the import content are skipped silently, (2) matches against the saved store increment dups, and (3) genuinely new items are appended. The assertion message ‘duplicate WIF(s)’ now only fires when all imported keys matched already-saved keys, which is the intended behavior. A test is updated to verify that a paper wallet containing two identical WIFs results in only one imported key and a two-item menu.
Changed components
shared/wif.py: WIFStore.import_wif()testing/test_wif.py: test_wif_store_import_paper_walletInspect captured patch +8 / −4
diff --git a/shared/wif.py b/shared/wif.py
index cbd9cd1..4e91bb5 100644
--- a/shared/wif.py
+++ b/shared/wif.py
@@ -299,6 +299,7 @@ class WIFStore(MenuSystem):
got = got.replace(',', ' ').split()
saved = settings.get("wifs", [])
+ len_saved = len(saved)
try:
new_wifs = []
@@ -322,15 +323,17 @@ class WIFStore(MenuSystem):
pk = b2a_hex(kp.pubkey().to_bytes()).decode()
item = (pk, sk)
+ if item in new_wifs:
+ # duplicate in import content
+ continue
- if item not in saved: # ignore dups
- new_wifs.append(item)
- else:
+ if item in saved: # ignore dups
dups += 1
+ else:
+ new_wifs.append(item)
assert new_wifs, 'no valid WIF found' if not dups else 'duplicate WIF(s)'
- len_saved = len(saved)
if (len_saved + len(new_wifs)) > self.MAX_ITEMS:
await ux_show_story("Max %d items allowed in WIF Store.\n\nAttempted to import %d keys,"
" while remaining WIF store capacity is only %d. Please, make room"
diff --git a/testing/test_wif.py b/testing/test_wif.py
index 7b2e49e..c268801 100644
--- a/testing/test_wif.py
+++ b/testing/test_wif.py
@@ -82,6 +82,7 @@ def test_wif_store_import_paper_wallet(goto_home, pick_menu_item, press_select,
menu = cap_menu()
assert "Import WIF" in menu
+ assert len(menu) == 2 # only one WIF imported from paper wallet that contins 2x same WIF
pick_menu_item(menu[1])
pick_menu_item("Detail")
time.sleep(.1)
Why this scored 27/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.