SFT-5768: improved seed word view warning
What changed, and why it matters
This commit changes the on-screen warnings shown to users before they view their wallet recovery seed words. It adds clearer anti-scam language and an extra confirmation step, but does not change how seed words are stored, generated, or protected. There is no security vulnerability in the code change itself.
No security action required; this is a user-experience and anti-scam messaging improvement.
Security signals we found
UI text change only
Adds anti-scam user warning
No changes to seed handling, storage, or access control
Evidence from the diff
The patch modifies two UI flow files in the Passport firmware. SeedWarningFlow gains a new optional ‘view_text’ parameter and a new ‘scam_warning’ page that warns users not to share seed words with apps or websites. The intro text is simplified to a scam-prevention message, and the final confirmation prompt is reworded. ViewSeedWordsFlow passes ‘Export’ as the view_text when invoking the warning flow. No cryptographic, storage, or access-control logic is altered.
Changed components
ports/stm32/boards/Passport/modules/flows/seed_warning_flow.pyports/stm32/boards/Passport/modules/flows/view_seed_words_flow.pyInspect captured patch +40 / −11
diff --git a/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py b/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py
index 5d99471..86b36b2 100644
--- a/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py
+++ b/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py
@@ -13,7 +13,8 @@ class SeedWarningFlow(Flow):
info_type_text=None,
initial=False,
allow_skip=True,
- key_manager=False):
+ key_manager=False,
+ view_text="View"):
self.mention_passphrase = mention_passphrase
self.action_text = action_text or "display your seed words"
self.continue_text = continue_text or "funds"
@@ -21,6 +22,7 @@ class SeedWarningFlow(Flow):
self.allow_skip = allow_skip
self.initial = initial
self.key_manager = key_manager
+ self.view_text = view_text or "View"
initial_state = self.show_skippable if (initial and allow_skip) else self.show_intro
super().__init__(initial_state=initial_state, name='SeedWarningFlow')
@@ -51,10 +53,13 @@ Would you like to view them now?'''
from pages import InfoPage
from utils import is_passphrase_active
- if self.mention_passphrase and is_passphrase_active():
- text = 'Passport is about to {} and passphrase'.format(self.action_text)
+ if self.key_manager:
+ if self.mention_passphrase and is_passphrase_active():
+ text = 'Passport is about to {} and passphrase'.format(self.action_text)
+ else:
+ text = 'Passport is about to {}'.format(self.action_text)
else:
- text = 'Passport is about to {}'.format(self.action_text)
+ text = 'Foundation and other legitimate companies will never ask you to share these words outside of Passport.'
# Empty microns have no action, so backing out isn't allowed
left_micron = microns.Back if self.allow_skip else None
@@ -77,6 +82,27 @@ Would you like to view them now?'''
self.set_result(True)
return
+ self.goto(self.scam_warning)
+
+ async def scam_warning(self):
+ from pages import InfoPage
+ import microns
+ import lvgl as lv
+
+ left_micron = microns.Back
+ right_micron = microns.Forward
+
+ text = 'Any request to share these words or enter them ' \
+ 'into an app or website is a scam.'
+
+ result = await InfoPage(
+ icon=lv.LARGE_ICON_SEED, text=text,
+ left_micron=left_micron, right_micron=right_micron).show()
+
+ if not result:
+ self.back()
+ return
+
self.goto(self.confirm_show)
async def prompt_backup(self):
@@ -92,21 +118,23 @@ Would you like to view them now?'''
self.back()
return
- self.goto(self.confirm_show)
+ self.goto(self.scam_warning)
async def confirm_show(self):
from pages import QuestionPage
import microns
- text = 'Anyone requesting you expose {} outside Passport ' \
- 'will gain full control over your {}. Take care.' \
- .format(self.info_type_text, self.continue_text)
+ # text = 'Anyone requesting you expose {} outside Passport ' \
+ # 'will gain full control over your {}. Take care.' \
+ # .format(self.info_type_text, self.continue_text)
+ text = 'Anyone with access to your seed words gains full control over your funds. {} your seed words now?'.format(self.view_text)
+
left_micron = microns.Cancel
if not self.allow_skip:
left_micron = None
- else:
- text += '\n\nContinue?'
+ # else:
+ # text += '\n\nContinue?'
result = await QuestionPage(text, left_micron=left_micron).show()
self.set_result(result)
diff --git a/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py b/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py
index e9bf1b7..f53904e 100644
--- a/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py
+++ b/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py
@@ -136,7 +136,8 @@ class ViewSeedWordsFlow(Flow):
mention_passphrase=self.mention_passphrase,
initial=self.initial,
allow_skip=self.allow_skip,
- key_manager=self.key_manager).run()
+ key_manager=self.key_manager,
+ view_text="Export").run()
if not result:
self.back()
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.