sign_tx: suppress validation/change attribution for green 2of3 outputs
What changed, and why it matters
This update fixes a security gap in how Blockstream Jade signs Bitcoin transactions for a specific wallet type called Green 2of3. Previously, the device trusted the connected app to supply a recovery public key and might silently treat an output as 'change' going back to the user's own wallet. A malicious or compromised companion app could have supplied a fake recovery key, tricking the device into marking a payment to an attacker's address as safe internal change. The fix forces the user to manually verify such outputs on the device screen instead of trusting the app, matching the behavior already used for PSBT signing.
Users relying on Green 2of3 wallets with Jade should upgrade firmware to include this commit. Until the future registration feature lands, expect to manually confirm all 2of3 outputs (including legitimate change) on the device screen during transaction signing. Developers should avoid trusting host-provided xpubs for change attribution and prioritize on-device registration as indicated by the TODO.
Security signals we found
Host-supplied recovery_xpub was trusted for change attribution
Change output could be misattributed without user confirmation
Fix suppresses automatic validation for Green 2of3 outputs
Aligns sign_tx with existing sign_psbt behavior
TODO indicates future on-device registration feature
Evidence from the diff
In main/process/sign_tx.c, the code now detects Green 2of3 outputs by checking whether a recovery_xpub field is present. When this is the case, it overrides is_change to false and skips setting OUTPUT_FLAG_VALIDATED. This prevents the hardware wallet from automatically validating/attributing change based on a host-provided recovery xpub that is not registered on the device. The commit notes this aligns sign_tx with sign_psbt behavior and that a future update will support on-device registration of 2of3 accounts to restore automatic change detection.
Changed components
main/process/sign_tx.cGreen 2of3 transaction signing flowOutput validation/change attribution logicInspect captured patch +17 / −1
diff --git a/main/process/sign_tx.c b/main/process/sign_tx.c
index 591c97a..0b8d64b 100644
--- a/main/process/sign_tx.c
+++ b/main/process/sign_tx.c
@@ -139,6 +139,7 @@ static bool params_signing_outputs(jade_process_t* process, const CborValue* par
size_t script_len = 0;
uint8_t script[WALLY_SCRIPTPUBKEY_P2WSH_LEN]; // Sufficient
size_t written = 0;
+ bool is_green_2of3 = false;
// If multisig, need to verify against the registered multisig wallets
if (rpc_has_field_data("multisig_name", &arrayItem)) {
@@ -229,6 +230,15 @@ static bool params_signing_outputs(jade_process_t* process, const CborValue* par
written = 0;
char xpubrecovery[120]; // Should be sufficient as all xpubs should be <= 112
rpc_get_string("recovery_xpub", sizeof(xpubrecovery), &arrayItem, xpubrecovery, &written);
+ is_green_2of3 = written != 0;
+ if (is_green_2of3 && is_change) {
+ // Green 2of3: We don't trust the host-provided xpub, so
+ // force the user to validate this probable change output.
+ // TODO: Allow registration of 2of3 accounts so the user
+ // doesn't have to validate legitimate change outputs.
+ JADE_LOGD("Ignoring 2of3 change identification");
+ is_change = false;
+ }
// Optional 'blocks' for csv outputs
rpc_get_sizet("csv_blocks", &arrayItem, &csv_blocks);
@@ -296,7 +306,13 @@ static bool params_signing_outputs(jade_process_t* process, const CborValue* par
JADE_LOGI("Output %u receive path/script validated", i);
// Set appropriate flags
- outinfo->flags |= OUTPUT_FLAG_VALIDATED;
+ if (!is_green_2of3) {
+ // Note for Green 2of3 we don't trust the host-provided xpub, so
+ // we do not mark this output as a validated wallet output.
+ // TODO: Allow registration of 2of3 accounts so the user
+ // doesn't have to confirm legitimate wallet outputs.
+ outinfo->flags |= OUTPUT_FLAG_VALIDATED;
+ }
if (is_change) {
outinfo->flags |= OUTPUT_FLAG_CHANGE;
}
Why this scored 72/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.