What changed, and why it matters
This commit is a minor code cleanup in the COLDCARD firmware's file picker. It moves the validation of filename suffixes earlier in the function and slightly changes the wording of an on-screen message shown when no matching files are found. There is no indication this fixes a security bug or introduces a vulnerability.
No security action needed. Treat as routine refactoring/cleanup.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff refactors file_picker() in shared/actions.py: suffix normalization and the assertion that all suffixes start with a dot are moved from inside the directory-listing loop to the top of the function. The filtering logic is reordered so hidden files (names starting with ‘.’) are skipped before suffix matching. The user-facing message for missing files is changed from ‘.7z,.txt’ style to ‘.7z OR .txt’ style. Tests in testing/test_ux.py are updated to match the new message format. No functional behavior change is evident beyond message text.
Changed components
shared/actions.py:file_picker()testing/test_ux.py:test_file_picker_suffixesInspect captured patch +16 / −13
diff --git a/shared/actions.py b/shared/actions.py
index dfb371c..a0a7f65 100644
--- a/shared/actions.py
+++ b/shared/actions.py
@@ -1728,8 +1728,13 @@ async def file_picker(suffix=None, min_size=1, max_size=1000000, taster=None,
# - escape: allow these chars to skip picking process
# - slot_b: None=>pick slot w/ card in it, or A if both.
# - allow_batch: adds an "all of the above" choice: ("menu label", menu_handler)
- # suffix argument MUST contain the dot (.), if list of suffixes - all MUST contain the dot
+ # - suffix argument MUST contain the dot (.txt), if list of suffixes, all MUST
+ if suffix:
+ # actually make it a list of "suffixes"
+ if not isinstance(suffix, list):
+ suffix = [suffix]
+ assert all(s[0] == '.' for s in suffix)
if choices is None:
choices = []
@@ -1743,15 +1748,13 @@ async def file_picker(suffix=None, min_size=1, max_size=1000000, taster=None,
# ignore subdirs
continue
- if suffix:
- if not isinstance(suffix, list):
- suffix = [suffix]
-
- assert all(s[0] == "." for s in suffix)
- if not any([fn.lower().endswith(s) for s in suffix]):
- continue
+ if fn[0] == '.':
+ # unix-style hidden files
+ continue
- if fn[0] == '.': continue
+ if suffix and not any(fn.lower().endswith(s) for s in suffix):
+ # wrong suffix, skip
+ continue
full_fname = path + '/' + fn
@@ -1797,7 +1800,7 @@ async def file_picker(suffix=None, min_size=1, max_size=1000000, taster=None,
if none_msg:
msg += none_msg
if suffix:
- msg += '\n\nThe filename must end in: %s' % ",".join(["*" + s for s in suffix])
+ msg += '\n\nThe filename must end in: ' + ' OR '.join(suffix)
msg += '\n\nMaybe insert (another) SD card and try again?'
diff --git a/testing/test_ux.py b/testing/test_ux.py
index bd206cd..324538c 100644
--- a/testing/test_ux.py
+++ b/testing/test_ux.py
@@ -1172,7 +1172,7 @@ def test_file_picker_suffixes(pick_menu_item, goto_home, cap_story, microsd_wipe
time.sleep(.1)
_, story = cap_story()
assert "No suitable files found" in story
- assert "The filename must end in: *.7z,*.txt" in story
+ assert "The filename must end in: .7z OR .txt" in story
press_select()
goto_home()
@@ -1183,7 +1183,7 @@ def test_file_picker_suffixes(pick_menu_item, goto_home, cap_story, microsd_wipe
time.sleep(.1)
_, story = cap_story()
assert "No suitable files found" in story
- assert "The filename must end in: *.pdf" in story
+ assert "The filename must end in: .pdf" in story
goto_home()
pick_menu_item("Advanced/Tools")
@@ -1192,7 +1192,7 @@ def test_file_picker_suffixes(pick_menu_item, goto_home, cap_story, microsd_wipe
time.sleep(.1)
_, story = cap_story()
assert "No suitable files found" in story
- assert "The filename must end in: *.txt,*.json" in story
+ assert "The filename must end in: .txt OR .json" in story
microsd_wipe()
Why this scored 12/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.