Add missing bound check in fpt_der_data_callback
What changed, and why it matters
This commit fixes a missing safety check in the Ledger Bitcoin app when reading BIP32 derivation data from a PSBT (Partially Signed Bitcoin Transaction). For non-Taproot transactions, the app was not verifying that the derivation data was not longer than the maximum supported size before copying it into a fixed-size internal buffer. This could allow a malicious or malformed PSBT to overflow that buffer, potentially corrupting memory and affecting the device's behavior during transaction signing.
Apply this patch and review adjacent PSBT parsing code for similar missing length validations, especially where externally controlled length values are used to size or index into fixed buffers. Consider fuzzing PSBT derivation fields and running static analysis for buffer bounds.
Security signals we found
Missing bounds check on externally supplied length field
Potential buffer overflow in fixed-size output buffer during PSBT parsing
Fix adds explicit length validation before memory copy preparation
Error path sets result code and returns early rather than continuing
Evidence from the diff
In extract_bip32_derivation.c, the function fpt_der_data_callback computes out_data_length for Taproot inputs and checks it against 4 * (1 + MAX_BIP32_PATH_STEPS). However, for non-Taproot inputs, it previously assigned cs->out_data_length = cs->total_data_length without any upper bound check. The patch adds a guard so that if cs->total_data_length exceeds the maximum supported derivation length, the callback sets cs->result = -1 and returns early. This prevents a malformed PSBT with an oversized BIP32 derivation field from being processed.
Changed components
src/handler/sign_psbt/extract_bip32_derivation.cfpt_der_data_callback functionPSBT BIP32 derivation extraction for non-Taproot inputsInspect captured patch +7 / −1
diff --git a/src/handler/sign_psbt/extract_bip32_derivation.c b/src/handler/sign_psbt/extract_bip32_derivation.c
index 7071747..1cd5d9a 100644
--- a/src/handler/sign_psbt/extract_bip32_derivation.c
+++ b/src/handler/sign_psbt/extract_bip32_derivation.c
@@ -37,11 +37,17 @@ static void fpt_der_data_callback(buffer_t *data, void *callback_state) {
// on the first call, compute the length the fingerprint + derivation part of the message.
// - if non-taproot, then it's the entire message;
// - if taproot, it's the message after the hashes are removed.
+ int max_out_data_length = 4 * (1 + MAX_BIP32_PATH_STEPS);
if (cs->out_data_length == -1) {
bool is_tap = cs->psbt_key_type == PSBT_IN_TAP_BIP32_DERIVATION ||
cs->psbt_key_type == PSBT_OUT_TAP_BIP32_DERIVATION;
if (!is_tap) {
+ if (cs->total_data_length > max_out_data_length) {
+ PRINTF("BIP32 derivation longer than supported in psbt derivation\n");
+ cs->result = -1;
+ return;
+ }
cs->out_data_length = cs->total_data_length;
} else {
// While BIP-0174 defines the number of hashes as a compact size integer, this
@@ -63,7 +69,7 @@ static void fpt_der_data_callback(buffer_t *data, void *callback_state) {
int out_data_length = cs->total_data_length - 1 - 32 * (int) n_hashes;
- if (out_data_length > 4 * (1 + MAX_BIP32_PATH_STEPS)) {
+ if (out_data_length > max_out_data_length) {
PRINTF("BIP32 derivation longer than supported in psbt derivation\n");
cs->result = -1;
return;
Why this scored 60/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.