refactor(core): use simpler `interact` in FIDO & ButtonRequest waiting
What changed, and why it matters
This commit is a straightforward internal code cleanup. It replaces several direct uses of a lower-level UI helper (`Layout(...).get_result()`) with a simpler wrapper function (`interact_simple`). The behavior described in the comments—specifically that the waiting screen must not start its own ButtonRequest handler—is preserved in the new helper usage. There is no indication this change fixes or introduces a security vulnerability.
No security action required. Treat as normal code maintenance. If reviewing, verify that `interact_simple` indeed does not attach a ButtonRequest handler, since `protocol_common.py` relies on that invariant.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff refactors FIDO2 and ButtonRequest waiting code across multiple Trezor Core UI layout backends (bolt, caesar, delizia, eckhart) and protocol_common.py. It removes direct instantiation of trezor.ui.Layout and calls to get_result(), replacing them with interact_simple() imported from trezor.ui.layouts.common. In protocol_common.py, the explicit layout.start() and the assertion that layout.button_request_handler is None are removed, but the comment explaining why ButtonRequest handling must be avoided is retained and updated. The change is described by the vendor as a refactor with no changelog entry.
Changed components
core/src/apps/webauthn/fido2.pycore/src/trezor/ui/layouts/bolt/fido.pycore/src/trezor/ui/layouts/caesar/fido.pycore/src/trezor/ui/layouts/delizia/fido.pycore/src/trezor/ui/layouts/eckhart/fido.pycore/src/trezor/wire/protocol_common.pyInspect captured patch +14 / −27
diff --git a/core/src/apps/webauthn/fido2.py b/core/src/apps/webauthn/fido2.py
index 62e3d7bd..a579223e 100644
--- a/core/src/apps/webauthn/fido2.py
+++ b/core/src/apps/webauthn/fido2.py
@@ -8,8 +8,7 @@ import storage.device as storage_device
from trezor import TR, config, io, log, loop, utils, wire, workflow
from trezor.crypto import hashlib
from trezor.crypto.curve import nist256p1
-from trezor.ui import Layout
-from trezor.ui.layouts import error_popup
+from trezor.ui.layouts import error_popup, interact_simple
from apps.common import cbor
from apps.common.lock_manager import set_homescreen
@@ -638,7 +637,7 @@ async def _show_error_popup(
button=button,
timeout_ms=timeout_ms,
) as popup:
- await Layout(popup).get_result()
+ await interact_simple(popup)
async def _confirm_bogus_app(title: str) -> None:
diff --git a/core/src/trezor/ui/layouts/bolt/fido.py b/core/src/trezor/ui/layouts/bolt/fido.py
index e011c65f..a90f1718 100644
--- a/core/src/trezor/ui/layouts/bolt/fido.py
+++ b/core/src/trezor/ui/layouts/bolt/fido.py
@@ -1,9 +1,8 @@
import trezorui_api
-from trezor import ui
from trezor.enums import ButtonRequestType
from trezor.ui.layouts import show_error_and_raise
-from ..common import interact
+from ..common import interact, interact_simple
async def confirm_fido(
@@ -56,8 +55,7 @@ async def confirm_fido_reset() -> bool:
description=TR.words__really_wanna,
reverse=True,
) as layout:
- confirm = ui.Layout(layout)
- return (await confirm.get_result()) is trezorui_api.CONFIRMED
+ return await interact_simple(layout) is trezorui_api.CONFIRMED
async def credential_warning(br_name: str, content: str) -> None:
diff --git a/core/src/trezor/ui/layouts/caesar/fido.py b/core/src/trezor/ui/layouts/caesar/fido.py
index b7163068..2cb9aa75 100644
--- a/core/src/trezor/ui/layouts/caesar/fido.py
+++ b/core/src/trezor/ui/layouts/caesar/fido.py
@@ -1,9 +1,8 @@
import trezorui_api
-from trezor import ui
from trezor.enums import ButtonRequestType
from trezor.ui.layouts import show_error_and_raise
-from ..common import interact
+from ..common import interact, interact_simple
async def confirm_fido(
@@ -42,7 +41,7 @@ async def confirm_fido_reset() -> bool:
verb_cancel="",
verb=TR.buttons__confirm,
) as confirm:
- return (await ui.Layout(confirm).get_result()) is trezorui_api.CONFIRMED
+ return await interact_simple(confirm) is trezorui_api.CONFIRMED
async def credential_warning(br_name: str, content: str) -> None:
diff --git a/core/src/trezor/ui/layouts/delizia/fido.py b/core/src/trezor/ui/layouts/delizia/fido.py
index ef0ec3da..7781815d 100644
--- a/core/src/trezor/ui/layouts/delizia/fido.py
+++ b/core/src/trezor/ui/layouts/delizia/fido.py
@@ -1,9 +1,8 @@
import trezorui_api
-from trezor import ui
from trezor.enums import ButtonRequestType
from trezor.ui.layouts import show_error_and_raise
-from ..common import interact
+from ..common import interact, interact_simple
async def confirm_fido(
@@ -50,8 +49,7 @@ async def confirm_fido_reset() -> bool:
reverse=True,
prompt_screen=True,
) as layout:
- confirm = ui.Layout(layout)
- return (await confirm.get_result()) is trezorui_api.CONFIRMED
+ return await interact_simple(layout) is trezorui_api.CONFIRMED
async def credential_warning(br_name: str, content: str) -> None:
diff --git a/core/src/trezor/ui/layouts/eckhart/fido.py b/core/src/trezor/ui/layouts/eckhart/fido.py
index 0d59d3e2..78ea3e1b 100644
--- a/core/src/trezor/ui/layouts/eckhart/fido.py
+++ b/core/src/trezor/ui/layouts/eckhart/fido.py
@@ -1,9 +1,9 @@
import trezorui_api
-from trezor import TR, ui
+from trezor import TR
from trezor.enums import ButtonRequestType
from trezor.ui.layouts import show_error_and_raise
-from ..common import interact
+from ..common import interact, interact_simple
async def confirm_fido(
@@ -51,8 +51,7 @@ async def confirm_fido_reset() -> bool:
allow_cancel=True,
danger=True,
) as layout:
- confirm = ui.Layout(layout)
- return (await confirm.get_result()) is trezorui_api.CONFIRMED
+ return await interact_simple(layout) is trezorui_api.CONFIRMED
async def credential_warning(br_name: str, content: str) -> None:
diff --git a/core/src/trezor/wire/protocol_common.py b/core/src/trezor/wire/protocol_common.py
index c460ae76..0e02875b 100644
--- a/core/src/trezor/wire/protocol_common.py
+++ b/core/src/trezor/wire/protocol_common.py
@@ -138,7 +138,7 @@ _UNRESPONSIVE_WARNING_TIMEOUT_MS = const(2000)
async def _waiting_screen(raise_on_cancel: type[Exception] | None) -> None:
import trezorui_api
from trezor import TR
- from trezor.ui import Layout
+ from trezor.ui.layouts import interact_simple
if raise_on_cancel is not None:
verb = TR.buttons__abort
@@ -155,15 +155,9 @@ async def _waiting_screen(raise_on_cancel: type[Exception] | None) -> None:
danger=False,
allow_cancel=False,
) as obj:
- # Block until the user confirmation.
# Don't use `interact` to avoid cancelling current workflow.
- layout = Layout(obj)
- layout.start()
- # This task doesn't have access to I/O context - see `ButtonRequestHandler.join()`.
- # Therefore, the new layout won't start its own ButtonRequest handler,
- # avoiding interference with the existing layout (the one we are waiting for).
- assert layout.button_request_handler is None
- await layout.get_result()
+ # The new layout won't start its own ButtonRequest handler, avoiding interference with the existing layout (the one we are waiting for).
+ await interact_simple(obj)
if raise_on_cancel:
raise raise_on_cancel()
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.