fix(core/eckhart): use a timeout when showing FIDO-related errors
What changed, and why it matters
This commit fixes a user-interface bug on the Trezor T3W1 hardware wallet. When a FIDO2/U2F security-key operation failed, the error popup was shown with a blank, non-functional button instead of automatically closing after a timeout. The fix makes the error screen close after the intended number of milliseconds (4 seconds in the FIDO2 case), so users are no longer stuck on a dead-end screen.
Low priority: include in regular firmware release notes as a UI/UX fix. No immediate security response required; verify that the 4-second timeout does not interfere with accessibility or user confirmation of critical security errors.
Security signals we found
UI flow bug in security-key (FIDO2/U2F) error handling
Previously ignored timeout parameter could leave user stuck on error screen
Fix restores intended automatic dismissal behavior
Evidence from the diff
In the Eckhart UI layout code (Trezor T3W1), the confirm_action method ignored its time_ms parameter (it was prefixed with an underscore). For FIDO-related error screens, callers pass a non-zero timeout expecting the screen to dismiss automatically, but the previous code always built a single-button ActionBar with no timeout, leaving an ‘empty’ button visible. The patch uses the time_ms value: if it is zero it keeps the original single-button behavior; otherwise it creates an ActionBar::new_timeout with Duration::from_millis(time_ms). The changelog notes this closes FIDO2 error popups after 4 seconds.
Changed components
core/embed/rust/src/ui/layout_eckhart/ui_firmware.rsTrezor T3W1 (Eckhart UI layout)FIDO2/U2F error popup flowInspect captured patch +7 / −2
diff --git a/core/.changelog.d/6984.fixed b/core/.changelog.d/6984.fixed
new file mode 100644
index 00000000..7f4b4089
--- /dev/null
+++ b/core/.changelog.d/6984.fixed
@@ -0,0 +1 @@
+[T3W1] Close FIDO2 error popup after 4 seconds.
diff --git a/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs b/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs
index 73e26ce6..1b90be08 100644
--- a/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs
+++ b/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs
@@ -1016,7 +1016,7 @@ impl FirmwareUI for UIEckhart {
button: TString<'static>,
description: TString<'static>,
allow_cancel: bool,
- _time_ms: u32,
+ time_ms: u32,
) -> Result<Gc<LayoutObj>, Error> {
let content = Paragraphs::new(Paragraph::new(&theme::firmware::TEXT_REGULAR, description))
.with_placement(LinearPlacement::vertical());
@@ -1027,7 +1027,11 @@ impl FirmwareUI for UIEckhart {
Button::with_text(button),
)
} else {
- ActionBar::new_single(Button::with_text(button))
+ let button = Button::with_text(button);
+ match time_ms {
+ 0 => ActionBar::new_single(button),
+ _ => ActionBar::new_timeout(button, Duration::from_millis(time_ms)),
+ }
};
let screen = TextScreen::new(content)
.with_header(
Why this scored 20/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.