What changed, and why it matters
This commit removes several internal 'debug' flags from normal production builds of the Trezor firmware and keeps them only in builds that have the optional 'ui_debug' feature enabled. These flags are used by automated tests (debuglink) to navigate menus and identify cancel buttons; they do not directly control security checks. The change reduces the chance that test-only state could accidentally affect or leak information in production firmware, but it is a cleanup rather than a fix for an active vulnerability.
Treat as a defensive hardening/cleanup commit. No urgent action is required, but verify that production release builds do not enable the ui_debug feature and that automated tests still compile and pass with ui_debug enabled.
Security signals we found
Reduction of debug/test-only state in production binaries
Conditional compilation used to limit debuglink metadata to debug builds
No functional security logic changed; no input validation, cryptography, or access control modified
Evidence from the diff
The patch gates struct fields and builder methods behind #[cfg(feature = “ui_debug”)] in six Rust UI components across three layouts (caesar, delizia, eckhart). Fields such as has_menu, has_flow_menu, and is_cancel, plus their with_menu/with_external_menu/with_flow_menu/set_is_cancel setters, are now compiled only when the ui_debug feature is active. In non-debug builds the setters become no-ops returning self unchanged. The commit message calls this a chore and explicitly marks it [no changelog].
Changed components
core/embed/rust/src/ui/layout_caesar/component/flow.rscore/embed/rust/src/ui/layout_caesar/component/show_more.rscore/embed/rust/src/ui/layout_delizia/component/button.rscore/embed/rust/src/ui/layout_delizia/component/frame.rscore/embed/rust/src/ui/layout_eckhart/component/button.rscore/embed/rust/src/ui/layout_eckhart/firmware/text_screen.rsInspect captured patch +52 / −1
diff --git a/core/embed/rust/src/ui/layout_caesar/component/flow.rs b/core/embed/rust/src/ui/layout_caesar/component/flow.rs
index 28ce6fe4..d6536521 100644
--- a/core/embed/rust/src/ui/layout_caesar/component/flow.rs
+++ b/core/embed/rust/src/ui/layout_caesar/component/flow.rs
@@ -35,6 +35,7 @@ where
/// Possibly enforcing the second button to be ignored after some time after
/// pressing the first button
ignore_second_button_ms: Option<u32>,
+ #[cfg(feature = "ui_debug")]
has_menu: bool,
}
@@ -62,6 +63,7 @@ where
return_confirmed_index: false,
show_scrollbar: true,
ignore_second_button_ms: None,
+ #[cfg(feature = "ui_debug")]
has_menu: false,
}
}
@@ -96,11 +98,17 @@ where
self.return_confirmed_index.then_some(self.page_counter)
}
+ #[cfg(feature = "ui_debug")]
pub fn with_menu(mut self, has_menu: bool) -> Self {
self.has_menu = has_menu;
self
}
+ #[cfg(not(feature = "ui_debug"))]
+ pub fn with_menu(self, _has_menu: bool) -> Self {
+ self
+ }
+
/// Getting new current page according to page counter.
/// Also updating the possible title and moving the scrollbar to correct
/// position.
diff --git a/core/embed/rust/src/ui/layout_caesar/component/show_more.rs b/core/embed/rust/src/ui/layout_caesar/component/show_more.rs
index 1accecd3..b8b4bb68 100644
--- a/core/embed/rust/src/ui/layout_caesar/component/show_more.rs
+++ b/core/embed/rust/src/ui/layout_caesar/component/show_more.rs
@@ -18,6 +18,7 @@ pub enum CancelInfoConfirmMsg {
pub struct ShowMore<T> {
content: Child<T>,
buttons: Child<ButtonController>,
+ #[cfg(feature = "ui_debug")]
has_menu: bool,
}
@@ -38,14 +39,21 @@ where
Self {
content: Child::new(content),
buttons: Child::new(ButtonController::new(btn_layout)),
+ #[cfg(feature = "ui_debug")]
has_menu: false,
}
}
+ #[cfg(feature = "ui_debug")]
pub fn with_menu(mut self, has_menu: bool) -> Self {
self.has_menu = has_menu;
self
}
+
+ #[cfg(not(feature = "ui_debug"))]
+ pub fn with_menu(self, _has_menu: bool) -> Self {
+ self
+ }
}
impl<T> Component for ShowMore<T>
diff --git a/core/embed/rust/src/ui/layout_delizia/component/button.rs b/core/embed/rust/src/ui/layout_delizia/component/button.rs
index af95654d..f1c9ddcc 100644
--- a/core/embed/rust/src/ui/layout_delizia/component/button.rs
+++ b/core/embed/rust/src/ui/layout_delizia/component/button.rs
@@ -33,6 +33,7 @@ pub struct Button {
long_press: ShortDuration, // long press requires non-zero duration
long_timer: Timer,
haptic: bool,
+ #[cfg(feature = "ui_debug")]
is_cancel: bool, // used by debuglink
}
@@ -54,6 +55,7 @@ impl Button {
long_press: ShortDuration::ZERO,
long_timer: Timer::new(),
haptic: true,
+ #[cfg(feature = "ui_debug")]
is_cancel: false,
}
}
@@ -105,11 +107,17 @@ impl Button {
self
}
+ #[cfg(feature = "ui_debug")]
pub fn set_is_cancel(mut self) -> Self {
self.is_cancel = true;
self
}
+ #[cfg(not(feature = "ui_debug"))]
+ pub fn set_is_cancel(self) -> Self {
+ self
+ }
+
pub fn enable_if(&mut self, ctx: &mut EventCtx, enabled: bool) {
if enabled {
self.enable(ctx);
diff --git a/core/embed/rust/src/ui/layout_delizia/component/frame.rs b/core/embed/rust/src/ui/layout_delizia/component/frame.rs
index 3a271655..162f4344 100644
--- a/core/embed/rust/src/ui/layout_delizia/component/frame.rs
+++ b/core/embed/rust/src/ui/layout_delizia/component/frame.rs
@@ -93,7 +93,9 @@ pub struct Frame<T> {
swipe: SwipeConfig,
horizontal_swipe: HorizontalSwipe,
margin: usize,
+ #[cfg(feature = "ui_debug")]
has_menu: bool,
+ #[cfg(feature = "ui_debug")]
has_flow_menu: bool,
}
@@ -117,7 +119,9 @@ where
swipe: SwipeConfig::new(),
horizontal_swipe: HorizontalSwipe::new(),
margin: 0,
+ #[cfg(feature = "ui_debug")]
has_menu: false,
+ #[cfg(feature = "ui_debug")]
has_flow_menu: false,
}
}
@@ -174,21 +178,31 @@ where
// `has_menu` is used to gradually introduce multi-item menus (#5189).
// TODO: After the migration, this flag should be set in `with_button()`.
+ #[cfg(feature = "ui_debug")]
pub fn with_external_menu(mut self) -> Self {
// Allow visiting this menu automatically by tests
self.has_menu = true;
self
}
+ #[cfg(not(feature = "ui_debug"))]
+ pub fn with_external_menu(self) -> Self {
+ self
+ }
// `has_flow_menu` is used to traverse old style (aka non-"external" menus)
// which are implemented as part of swipe flows.
// TODO: Once we have eventually replaced all these with new style "external
// menu" we should get rid of this flag and the related debuglink code.
+ #[cfg(feature = "ui_debug")]
pub fn with_flow_menu(mut self) -> Self {
// Allow visiting this menu automatically by tests
self.has_flow_menu = true;
self
}
+ #[cfg(not(feature = "ui_debug"))]
+ pub fn with_flow_menu(self) -> Self {
+ self
+ }
pub fn title_styled(mut self, style: TextStyle) -> Self {
self.header = self.header.styled(style);
diff --git a/core/embed/rust/src/ui/layout_eckhart/component/button.rs b/core/embed/rust/src/ui/layout_eckhart/component/button.rs
index 62e2fa8b..69ced096 100644
--- a/core/embed/rust/src/ui/layout_eckhart/component/button.rs
+++ b/core/embed/rust/src/ui/layout_eckhart/component/button.rs
@@ -46,6 +46,7 @@ pub struct Button {
long_timer: Timer,
haptic: bool,
subtext_marquee: Option<Marquee>,
+ #[cfg(feature = "ui_debug")]
is_cancel: bool, // used by debuglink
}
@@ -88,6 +89,7 @@ impl Button {
long_timer: Timer::new(),
haptic: true,
subtext_marquee,
+ #[cfg(feature = "ui_debug")]
is_cancel: false,
}
}
@@ -276,11 +278,17 @@ impl Button {
matches!(self.radius_or_gradient, RadiusOrGradient::Gradient(_))
}
+ #[cfg(feature = "ui_debug")]
pub fn set_is_cancel(mut self) -> Self {
self.is_cancel = true;
self
}
+ #[cfg(not(feature = "ui_debug"))]
+ pub fn set_is_cancel(self) -> Self {
+ self
+ }
+
pub fn enable_if(&mut self, ctx: &mut EventCtx, enabled: bool) {
if enabled {
self.enable(ctx);
diff --git a/core/embed/rust/src/ui/layout_eckhart/firmware/text_screen.rs b/core/embed/rust/src/ui/layout_eckhart/firmware/text_screen.rs
index 91f93567..6180c6d3 100644
--- a/core/embed/rust/src/ui/layout_eckhart/firmware/text_screen.rs
+++ b/core/embed/rust/src/ui/layout_eckhart/firmware/text_screen.rs
@@ -46,6 +46,7 @@ pub struct TextScreen<T> {
show_action_bar: bool,
show_page_counter: bool,
+ #[cfg(feature = "ui_debug")]
has_flow_menu: bool,
// TODO: swipe handling
// TODO: animations
@@ -74,6 +75,7 @@ where
background: None,
show_action_bar: false,
show_page_counter: false,
+ #[cfg(feature = "ui_debug")]
has_flow_menu: false,
}
}
@@ -116,7 +118,10 @@ where
// we should get rid of this flag and the related debuglink code.
pub fn with_flow_menu(mut self) -> Self {
// Allow visiting this menu automatically by tests
- self.has_flow_menu = true;
+ #[cfg(feature = "ui_debug")]
+ {
+ self.has_flow_menu = true;
+ }
self
}
Why this scored 18/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.