SIGHASH gating: status screen on disabled rejection
What changed, and why it matters
This commit is a user-experience improvement, not a security fix. When a Bitcoin transaction uses a non-standard sighash and the user has not enabled the 'Allow non-standard sighash' setting, the app already rejected the transaction. Now it also shows an on-screen message explaining why it was rejected, so the user is not left confused.
No security action required; treat as a normal UX enhancement. Continue standard review and testing.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change adds a new UI flow, ui_display_nondefault_sighash_disabled_flow(), invoked via ui_warn_nondefault_sighash_disabled() when preprocess_inputs() rejects a non-default sighash because app_settings_get_allow_nondefault_sighash() is false. The rejection logic and error code (SW_SECURITY_STATUS_NOT_SATISFIED / EC_SIGN_PSBT_NONDEFAULT_SIGHASH_NOT_ALLOWED) are unchanged; only a terminal status screen is added. No cryptographic, parsing, or access-control code is modified.
Changed components
src/handler/sign_psbt/preprocess_inputs.csrc/ui/display.csrc/ui/display.hsrc/ui/display_nbgl.cInspect captured patch +28 / −0
diff --git a/src/handler/sign_psbt/preprocess_inputs.c b/src/handler/sign_psbt/preprocess_inputs.c
index 0d04dec..2a5ff03 100644
--- a/src/handler/sign_psbt/preprocess_inputs.c
+++ b/src/handler/sign_psbt/preprocess_inputs.c
@@ -29,6 +29,7 @@
#include "bitvector.h"
#include "buffer.h"
#include "constants.h"
+#include "display.h"
#include "dispatcher.h"
#include "error_codes.h"
#include "get_merkleized_map.h"
@@ -300,6 +301,9 @@ bool __attribute__((noinline)) preprocess_inputs(
// "Allow non-standard sighash" in the application settings.
if (!app_settings_get_allow_nondefault_sighash()) {
PRINTF("Non-standard sighash rejected: setting not enabled\n");
+ // Show a clear on-device status so the user understands why the
+ // transaction was rejected
+ ui_warn_nondefault_sighash_disabled(dc);
SEND_SW_EC(dc,
SW_SECURITY_STATUS_NOT_SATISFIED,
EC_SIGN_PSBT_NONDEFAULT_SIGHASH_NOT_ALLOWED);
diff --git a/src/ui/display.c b/src/ui/display.c
index d233864..1cee839 100644
--- a/src/ui/display.c
+++ b/src/ui/display.c
@@ -226,6 +226,16 @@ bool ui_warn_nondefault_sighash(dispatcher_context_t *context) {
return io_ui_process(context);
}
+void ui_warn_nondefault_sighash_disabled(dispatcher_context_t *context) {
+#ifdef HAVE_AUTOAPPROVE_FOR_PERF_TESTS
+ return;
+#endif
+
+ UNUSED(context);
+ // Fire-and-forget terminal status
+ ui_display_nondefault_sighash_disabled_flow();
+}
+
bool ui_transaction_streaming_prompt(dispatcher_context_t *context) {
#ifdef HAVE_AUTOAPPROVE_FOR_PERF_TESTS
return true;
diff --git a/src/ui/display.h b/src/ui/display.h
index 72b80c1..42b00dc 100644
--- a/src/ui/display.h
+++ b/src/ui/display.h
@@ -170,6 +170,9 @@ bool ui_warn_unverified_segwit_inputs(dispatcher_context_t *context);
bool ui_warn_nondefault_sighash(dispatcher_context_t *context);
+// Shows a terminal status explaining that a non-standard sighash was rejected
+void ui_warn_nondefault_sighash_disabled(dispatcher_context_t *context);
+
bool ui_warn_high_fee(dispatcher_context_t *context);
/* These 3 functions have to be called in following order:
@@ -216,6 +219,8 @@ void ui_display_unverified_segwit_inputs_flows(void);
void ui_display_nondefault_sighash_flow(void);
+void ui_display_nondefault_sighash_disabled_flow(void);
+
void ui_warn_high_fee_flow(void);
void ui_display_register_wallet_policy_flow(void);
diff --git a/src/ui/display_nbgl.c b/src/ui/display_nbgl.c
index 722bc9f..b59ee5d 100644
--- a/src/ui/display_nbgl.c
+++ b/src/ui/display_nbgl.c
@@ -33,6 +33,7 @@ const char GA_RISK_EXTERNAL_INPUTS[] =
const char GA_RISK_NON_STD_SIGHASH[] =
"This transaction uses non-standard signing rules (modified sighash). You could spend more "
"than expected.";
+const char GA_NON_STD_SIGHASH_DISABLED[] = "Non-standard signing rules are disabled in settings";
const char GA_WARN_HIGH_FEES[] =
"This transaction has fees higher than 10% of the amount you're sending.";
#else
@@ -40,6 +41,7 @@ const char GA_SECURITY_RISK_TITLE[] = "Security risk";
const char GA_WARN_HIGH_FEES_TITLE[] = "High fees warning";
const char GA_RISK_EXTERNAL_INPUTS[] = "There are external inputs\nReject if not sure";
const char GA_RISK_NON_STD_SIGHASH[] = "Non-default sighash";
+const char GA_NON_STD_SIGHASH_DISABLED[] = "Non-standard\nsighash disabled\nin settings";
const char GA_WARN_HIGH_FEES[] = "Fees are above 10%\n of total amount";
#endif
@@ -463,6 +465,13 @@ void ui_display_nondefault_sighash_flow(void) {
ui_display_warning_generic(GA_RISK_NON_STD_SIGHASH);
}
+// Terminal status shown when a non-standard sighash is rejected because the
+// "Non-standard sighash" setting is disabled.
+void ui_display_nondefault_sighash_disabled_flow(void) {
+ ux_flow_response_false();
+ nbgl_useCaseStatus(GA_NON_STD_SIGHASH_DISABLED, false, ui_menu_main);
+}
+
// Statuses
void ui_display_post_processing_confirm_message(bool success) {
if (success) {
Why this scored 15/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.