Reject 0x80000000 as an unhardened step in wallet policy parsing
What changed, and why it matters
This commit fixes a boundary-check bug in how the Ledger Bitcoin app parses wallet policies (BIP-388). The app was supposed to reject any hardened derivation step in a specific range expression, but it allowed the value 2147483648 (0x80000000) because the check used 'greater than' instead of 'greater than or equal to'. That value actually represents a hardened step, which is forbidden here. The fix changes the comparison so 0x80000000 is correctly rejected. If accepted, it could later cause address derivation or signing to fail or behave unexpectedly.
Treat as a security-relevant correctness fix. Review whether any downstream code could be reached with 0x80000000 before this patch, and confirm that the rejection path is exercised by tests. Consider adding regression tests for boundary values 0x7FFFFFFF and 0x80000000 in /<M;N>/* parsing.
Security signals we found
Off-by-one boundary check in BIP-388 wallet policy parsing
Forbidden hardened derivation index accepted as unhardened
Potential failure or incorrect behavior in address derivation and signing
Input validation weakness in key expression range parsing
Evidence from the diff
In src/common/wallet.c, parse_keyexpr validates the M and N values in /
Changed components
src/common/wallet.cparse_keyexpr functionBIP-388 wallet policy key expression range parsingInspect captured patch +2 / −2
### src/common/wallet.c
@@ -560,7 +560,7 @@ static int parse_keyexpr(buffer_t *in_buf,
} else if (next_character == '<') {
buffer_seek_cur(in_buf, 1); // skip "<"
if (parse_unsigned_decimal(in_buf, &out->num_first) == -1 ||
- out->num_first > 0x80000000u) {
+ out->num_first >= BIP32_FIRST_HARDENED_CHILD) {
return WITH_ERROR(
-1,
"Expected /** or /<M;N>/* in key expression, with unhardened M and N");
@@ -571,7 +571,7 @@ static int parse_keyexpr(buffer_t *in_buf,
}
if (parse_unsigned_decimal(in_buf, &out->num_second) == -1 ||
- out->num_second > 0x80000000u) {
+ out->num_second >= BIP32_FIRST_HARDENED_CHILD) {
return WITH_ERROR(
-1,
"Expected /** or /<M;N>/* in key expression, with unhardened M and N");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.