show backup filename during backup password entry (Q only)
What changed, and why it matters
This commit is a user-interface improvement, not a security fix. When restoring a COLDCARD backup on the Q-series device, the screen now shows the backup filename above the password-entry prompt so the user knows which file they are unlocking. No code behavior that protects secrets was changed.
No security action needed; treat as a normal feature/UX enhancement.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change adds an optional line2 parameter to seed_word_entry() in shared/ux_q1.py and uses it in shared/backups.py to display the backup filename during restore password entry. Long filenames are truncated with an ellipsis. Tests were added to verify the filename appears on screen. There are no cryptographic, access-control, or vulnerability-related changes.
Changed components
shared/backups.pyshared/ux_q1.pyInspect captured patch +61 / −10
diff --git a/releases/Next-ChangeLog.md b/releases/Next-ChangeLog.md
index 127573c..eda7ca5 100644
--- a/releases/Next-ChangeLog.md
+++ b/releases/Next-ChangeLog.md
@@ -18,6 +18,6 @@ This lists the new changes that have not yet been published in a normal release.
## 1.3.5Q - 2025-10-xx
--
+- Enhancement: Show backup filename at the top of the screen during backup password entry
diff --git a/shared/backups.py b/shared/backups.py
index d7e5a1a..23bb3c9 100644
--- a/shared/backups.py
+++ b/shared/backups.py
@@ -570,9 +570,17 @@ async def restore_complete(fname_or_fd, temporary=False, words=True, usb=False):
if words:
if version.has_qwerty:
- from ux_q1 import seed_word_entry
- return await seed_word_entry('Enter Password:', num_pw_words,
- done_cb=done, has_checksum=False)
+ from ux_q1 import seed_word_entry, CHARS_W
+
+ basename = None
+ if isinstance(fname_or_fd, str):
+ basename = fname_or_fd.split('/')[-1]
+ if len(basename) > CHARS_W:
+ basename = basename[:16] + "⋯" + basename[-16:]
+
+ return await seed_word_entry("Enter Password%s:" % (" for" if basename else ""),
+ num_pw_words, done_cb=done, has_checksum=False,
+ line2=basename)
# give them a menu to pick from, and start picking
if usb:
diff --git a/shared/ux_q1.py b/shared/ux_q1.py
index 0f5255e..9f763ea 100644
--- a/shared/ux_q1.py
+++ b/shared/ux_q1.py
@@ -594,7 +594,7 @@ def ux_draw_words(y, num_words, words):
return rv
-async def seed_word_entry(prompt, num_words, has_checksum=True, done_cb=None):
+async def seed_word_entry(prompt, num_words, has_checksum=True, done_cb=None, line2=None):
# Accept a seed phrase, only
# - replaces WordNestMenu on Q1
# - max word length is 8, min is 3
@@ -604,13 +604,23 @@ async def seed_word_entry(prompt, num_words, has_checksum=True, done_cb=None):
assert num_words and prompt
+ not24 = (num_words != 24)
+
def redraw_words(wrds=None):
if not wrds:
wrds = ['' for _ in range(num_words)]
dis.clear()
dis.text(None, 0, prompt, invert=1)
- p = ux_draw_words(2 if num_words != 24 else 1, num_words, wrds)
+
+ Y = 2 if not24 else 1
+ if line2 and not24:
+ # add second line, if provided, but only if words length < 24
+ # currently only used to show backup filename during backup pwd entry
+ dis.text(None, 1, line2, invert=1)
+ Y += 1
+
+ p = ux_draw_words(Y, num_words, wrds)
return wrds, p
words, pos = redraw_words()
diff --git a/testing/conftest.py b/testing/conftest.py
index 3ea4d48..260409a 100644
--- a/testing/conftest.py
+++ b/testing/conftest.py
@@ -2321,9 +2321,9 @@ def restore_backup_unpacked(unit_test, pick_menu_item, cap_story, cap_menu,
return doit
@pytest.fixture
-def restore_backup_cs(unit_test, pick_menu_item, cap_story, cap_menu,
- press_select, word_menu_entry, get_setting, is_q1,
- need_keypress, scan_a_qr, cap_screen, enter_complex, restore_backup_unpacked):
+def restore_backup_cs(unit_test, pick_menu_item, cap_story, cap_menu, press_select, word_menu_entry,
+ get_setting, is_q1, need_keypress, scan_a_qr, cap_screen, enter_complex,
+ restore_backup_unpacked):
# restore backup with clear seed as first step
def doit(fn, passphrase, avail_settings=None, pass_way=None, custom_bkpw=False):
unit_test('devtest/clear_seed.py')
@@ -2342,7 +2342,7 @@ def restore_backup_cs(unit_test, pick_menu_item, cap_story, cap_menu,
pick_menu_item(fn)
time.sleep(.1)
- if is_q1 and pass_way and pass_way == "qr":
+ if is_q1 and pass_way and (pass_way == "qr"):
need_keypress(KEY_QR)
time.sleep(.1)
qr = ' '.join(w[:4] for w in passphrase)
@@ -2356,6 +2356,11 @@ def restore_backup_cs(unit_test, pick_menu_item, cap_story, cap_menu,
elif custom_bkpw:
enter_complex(passphrase, b39pass=False)
else:
+ # looking at word entry right now
+ if is_q1:
+ scr = cap_screen()
+ assert fn in scr # backup fname shown at the top
+ assert "Enter Password for:" in scr
word_menu_entry(passphrase, has_checksum=False)
restore_backup_unpacked(avail_settings=avail_settings)
diff --git a/testing/test_backup.py b/testing/test_backup.py
index 3a126ee..d066d51 100644
--- a/testing/test_backup.py
+++ b/testing/test_backup.py
@@ -744,4 +744,32 @@ def test_exit_dev_backup(tmp, unit_test, goto_home, pick_menu_item, need_keypres
pick_menu_item("Restore Bkup")
press_cancel()
+
+@pytest.mark.parametrize("fname", [
+ '03edd162a5f57eece68d8eea3891e2a150383a225187179ecb1599efe00d16dd70-ccbk.7z',
+ ('W'*31) + ".7z",
+])
+def test_backup_long_name_display(fname, goto_home, pick_menu_item, need_keypress, src_root_dir,
+ microsd_path, press_cancel, cap_screen):
+ fn = microsd_path(fname)
+ shutil.copy(f'{src_root_dir}/docs/backup.7z', fn)
+
+ goto_home()
+ pick_menu_item('Advanced/Tools')
+ pick_menu_item('Temporary Seed')
+ need_keypress("4")
+ pick_menu_item('Coldcard Backup')
+
+ time.sleep(.1)
+ pick_menu_item(fname)
+ time.sleep(.1)
+ scr = cap_screen()
+ if len(fname) > 34: # CHARS_W
+ assert fname[:16] in scr
+ assert fname[-16:] in scr
+ else:
+ assert fname in scr
+
+ press_cancel()
+
# EOF
Why this scored 15/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.