Summary
`confirm_helper()` (the path every other confirmation screen uses) detects both SOURCE truncation (`vsnprintf()` overflow) and RENDER truncation (text not fitting the OLED body), and shows an explicit "Cut Off ... Hold to continue anyway" screen with pagination in either case. `layoutU2FDialog()` reimplements the same `vsnprintf`+draw pattern standalone, discarding `vsnprintf`'s return (no SOURCE-truncation check) and calling `layout_standard_notification()` directly with no fit check and no pagination at all.
Impact (high)
This is the on-device consent dialog for CTAP2 passkey creation/use ("Create a passkey for %s?"/"Sign in to %s?") and legacy U2F register/authenticate, showing the host/relying-party-controlled `rp_id` (up to 253 chars, filled straight from CBOR input with no length reduction). Only ~100 characters actually render; anything past that is silently dropped with no ellipsis, no warning, no second page. The user approves based on a truncated prefix while the credential that gets created/used is bound to the FULL (unshown) `rp_id` -- `sha256_Raw()` hashes the complete string. The device shows less than what it's actually acting on.
Fix direction
Route `layoutU2FDialog()` through the same `confirm_body_fits()`/pagination machinery `confirm_helper()` already provides, or otherwise reject/truncate-with-warning an `rp_id`/app-name too long to fully display.
Summary
`confirm_helper()` (the path every other confirmation screen uses) detects both SOURCE truncation (`vsnprintf()` overflow) and RENDER truncation (text not fitting the OLED body), and shows an explicit "Cut Off ... Hold to continue anyway" screen with pagination in either case. `layoutU2FDialog()` reimplements the same `vsnprintf`+draw pattern standalone, discarding `vsnprintf`'s return (no SOURCE-truncation check) and calling `layout_standard_notification()` directly with no fit check and no pagination at all.
Impact (high)
This is the on-device consent dialog for CTAP2 passkey creation/use ("Create a passkey for %s?"/"Sign in to %s?") and legacy U2F register/authenticate, showing the host/relying-party-controlled `rp_id` (up to 253 chars, filled straight from CBOR input with no length reduction). Only ~100 characters actually render; anything past that is silently dropped with no ellipsis, no warning, no second page. The user approves based on a truncated prefix while the credential that gets created/used is bound to the FULL (unshown) `rp_id` -- `sha256_Raw()` hashes the complete string. The device shows less than what it's actually acting on.
Fix direction
Route `layoutU2FDialog()` through the same `confirm_body_fits()`/pagination machinery `confirm_helper()` already provides, or otherwise reject/truncate-with-warning an `rp_id`/app-name too long to fully display.