fix(gui): guard checkbox handlers against clicks on non-checkbox children
What changed, and why it matters
This commit fixes a user-interface bug in the Keystone 3 hardware wallet firmware. A screen that lets users pick options from checkboxes could crash or behave incorrectly if the user tapped on a label or other non-checkbox element inside the same area. The fix adds a simple safety check so the code only reacts when a real checkbox is tapped. It is a defensive hardening change rather than a clear exploit, but in a wallet firmware any UI crash during seed-phrase or share creation could be security-relevant because it might interrupt a sensitive backup workflow.
Treat as a low-risk hardening fix. Review whether the same pattern exists in other checkbox handlers across the firmware, and confirm that the active_id index cannot be manipulated to reference an invalid child. No urgent user action is indicated unless the vendor releases a security advisory.
Security signals we found
Defensive type validation added to event handler
Potential NULL pointer / type confusion in UI callback
Affected UI flows involve seed phrase and shamir share creation
No explicit security disclosure or CVE referenced in commit
Evidence from the diff
SelectCheckBoxHandler in gui_create_share_widgets.c and gui_single_phrase_widgets.c is an LVGL event callback registered on a parent ‘hint box’ object. It retrieves the event target with lv_event_get_target(e) and assumes it is a checkbox. The patch adds a type guard using lv_obj_check_type(actCb, &lv_checkbox_class) and also adds an oldCb == NULL guard in the share widget. Without the guard, clicking a child label or other non-checkbox object would proceed to treat it as a checkbox, potentially causing a NULL-pointer dereference, out-of-bounds child access, or undefined behavior. The change is small (+2/-2 lines) and defensive; it does not by itself demonstrate a reachable exploit, but it removes an unsafe assumption in security-critical UI flows (seed phrase / shamir share creation).
Changed components
src/ui/gui_widgets/gui_create_share_widgets.csrc/ui/gui_widgets/gui_single_phrase_widgets.cLVGL checkbox event handlersInspect captured patch +2 / −2
diff --git a/src/ui/gui_widgets/gui_create_share_widgets.c b/src/ui/gui_widgets/gui_create_share_widgets.c
index 2f3a563..faec5eb 100644
--- a/src/ui/gui_widgets/gui_create_share_widgets.c
+++ b/src/ui/gui_widgets/gui_create_share_widgets.c
@@ -642,7 +642,7 @@ static void SelectCheckBoxHandler(lv_event_t* e)
lv_obj_t *actCb = lv_event_get_target(e);
lv_obj_t *oldCb = lv_obj_get_child(g_noticeHintBox, *active_id);
- if (actCb == g_noticeHintBox || oldCb == NULL) {
+ if (actCb == g_noticeHintBox || oldCb == NULL || !lv_obj_check_type(actCb, &lv_checkbox_class)) {
return;
}
Vibrate(SLIGHT);
diff --git a/src/ui/gui_widgets/gui_single_phrase_widgets.c b/src/ui/gui_widgets/gui_single_phrase_widgets.c
index f44d59a..afaf3f5 100644
--- a/src/ui/gui_widgets/gui_single_phrase_widgets.c
+++ b/src/ui/gui_widgets/gui_single_phrase_widgets.c
@@ -260,7 +260,7 @@ static void SelectCheckBoxHandler(lv_event_t* e)
lv_obj_t *actCb = lv_event_get_target(e);
lv_obj_t *oldCb = lv_obj_get_child(g_noticeHintBox, *active_id);
- if (actCb == g_noticeHintBox) {
+ if (actCb == g_noticeHintBox || oldCb == NULL || !lv_obj_check_type(actCb, &lv_checkbox_class)) {
return;
}
Vibrate(SLIGHT);
Why this scored 35/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.