fix(core): raise "already pending" `FirmwareError` only on a new `ButtonRequest`
What changed, and why it matters
This is a small defensive fix inside the Trezor hardware wallet's user-interface code. It moves a debug-only sanity check so that it no longer fires when a screen layout simply returns nothing (None). Previously, the check could incorrectly raise a 'FirmwareError' before the code had a chance to notice there was no new button request. The change only affects debug builds and is unlikely to be directly exploitable by an attacker.
No urgent action required. Treat as routine code-quality hardening. Reviewers may verify that ButtonRequest queuing behavior remains unchanged in production builds and that no concurrent UI flows can leave stale entries in button_request_box.
Security signals we found
Debug-only assertion moved to reduce false-positive FirmwareError
No input validation or memory-safety change
No privilege boundary crossed
No changelog entry suggests routine/internal fix
Evidence from the diff
In core/src/trezor/ui/init.py, the Layout._button_request() method previously checked whether button_request_box was non-empty before calling self.layout.button_request(). If the layout returned None (meaning no new ButtonRequest), the early check could still trigger a wire.FirmwareError in debug builds. The patch moves the check after the None and self.context checks, so the ‘already pending’ FirmwareError is raised only when a new ButtonRequest is actually being enqueued. This is a hardening/debugging change, not a patch for an externally reachable vulnerability.
Changed components
core/src/trezor/ui/__init__.pyLayout._button_request()ButtonRequest handling flowInspect captured patch +6 / −6
diff --git a/core/src/trezor/ui/__init__.py b/core/src/trezor/ui/__init__.py
index d4f9986f8..32c08051a 100644
--- a/core/src/trezor/ui/__init__.py
+++ b/core/src/trezor/ui/__init__.py
@@ -334,12 +334,6 @@ class Layout(Generic[T]):
def _button_request(self) -> bool:
"""Process a button request coming out of the Rust layout."""
- if __debug__ and not self.button_request_box.is_empty():
- raise wire.FirmwareError(
- "button request already pending -- "
- "don't forget to yield your input flow from time to time ^_^"
- )
-
res = self.layout.button_request()
if res is None:
return False
@@ -347,6 +341,12 @@ class Layout(Generic[T]):
if self.context is None:
return False
+ if __debug__ and not self.button_request_box.is_empty():
+ raise wire.FirmwareError(
+ "button request already pending -- "
+ "don't forget to yield your input flow from time to time ^_^"
+ )
+
# in production, we don't want this to fail, hence replace=True
self.button_request_box.put(res, replace=True)
return True
Why this scored 25/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.