What changed, and why it matters
This commit fixes two error-handling bugs in Blockstream Jade's multisignature wallet code. In one case, an invalid multisig wallet record was detected but the function kept running instead of returning immediately, which could lead to using corrupted wallet data. In the other, a path-validation failure was silently ignored, so a bad signer path might be accepted. Both are correctness fixes that improve safety, but the diff alone does not prove they are exploitable attacks.
Treat as a security-relevant bug fix. Review whether the invalid-data fall-through could have been reached in production, and consider whether a firmware update or advisory is warranted for users storing multisig registrations on Jade.
Security signals we found
Missing return after setting error condition in validation path
Unchecked return value from security-relevant path validation
Multisignature wallet data integrity check bypass
Potential use of invalid/corrupted multisig registration data
Evidence from the diff
In main/multisig.c, multisig_load_from_storage() sets an error message when wallet data is invalid but previously fell through to free(registration) and return true. The patch adds an immediate free/return false. In main/process/process_utils.c, params_multisig_pubkeys() calls multisig_validate_paths() and previously ignored its boolean result; the patch now treats a false return as a fatal error with a descriptive message. These are defensive fixes for control-flow and validation bugs in multisig handling.
Changed components
main/multisig.c:multisig_load_from_storagemain/process/process_utils.c:params_multisig_pubkeysInspect captured patch +6 / −1
diff --git a/main/multisig.c b/main/multisig.c
index 2ecd231..bbeb49e 100644
--- a/main/multisig.c
+++ b/main/multisig.c
@@ -396,6 +396,8 @@ bool multisig_load_from_storage(const char* multisig_name, multisig_data_t* outp
|| !output->num_xpubs || output->num_xpubs > MAX_ALLOWED_SIGNERS
|| (output->master_blinding_key_len && output->master_blinding_key_len != MULTISIG_MASTER_BLINDING_KEY_SIZE)) {
*errmsg = "Multisig wallet data invalid";
+ free(registration);
+ return false;
}
free(registration);
diff --git a/main/process/process_utils.c b/main/process/process_utils.c
index cd698b7..3633967 100644
--- a/main/process/process_utils.c
+++ b/main/process/process_utils.c
@@ -242,7 +242,10 @@ bool params_multisig_pubkeys(const bool is_change, CborValue* params, multisig_d
bool flipped_change_element = false;
if (!all_paths_as_expected) {
bool unused;
- multisig_validate_paths(!is_change, &all_signer_paths, &flipped_change_element, &unused);
+ if (!multisig_validate_paths(!is_change, &all_signer_paths, &flipped_change_element, &unused)) {
+ *errmsg = "Expected a valid change or non-change signer path";
+ return false;
+ }
}
// If paths not as expected show a warning message and ask the user to confirm
Why this scored 42/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.