Triaged during the 7.14.2 residual pass and deferred out of 7.14.2 as low. Still present at release/7.14.2 head.
Evidence
lib/firmware/ethereum.c:598 (if (msg->gas_price.size + msg->gas_limit.size > 30)), display path at lib/firmware/ethereum.c:536-547
Assessment
Still present. ethereum.c changed substantially on this branch (the UnknownToken/AdvancedMode gate, the EIP-712 confirmation, the USER_CANCELLED branch) but line 598 is untouched, and ethereum_signing_init still requires only max_fee_per_gas for type 2 (ethereum.c:668-674), so gas_price.size is 0 on that path and the guard degenerates to gas_limit.size > 30. layoutEthereumFee then computes the displayed fee with bn_multiply(&val, &gas, &secp256k1.prime) at ethereum.c:547 — modular, so it wraps rather than saturating. The code defect is real: the guard reads a field the transaction does not use.
I checked the two ways this could escalate and both fail. There is no memory-safety angle: include/keepkey/transport/messages-ethereum.options pins max_fee_per_gas, gas_limit and value at max_size:32, so the memcpy(pad_val + (32 - len), ...) idiom in formatEthereumFeeEIP1559 (ethereum.c:519-521) and layoutEthereumFee (:543) can never underflow the destination. And the display lie is unreachable: making the product wrap needs max_fee_per_gas * gas_limit >= p, about 1.16e77 wei, while the entire ETH supply is on the order of 1.2e26 wei — and EIP-1559 requires the sender's balance to cover gas_limit * max_fee_per_gas at inclusion, so any parameter set large enough to wrap produces a transaction no node will ever include. For every product a fundable account could pay, the product is far below p and bn_multiply is exact, so the displayed figure is correct. Nothing signed under this defect can move funds.
Low, and file rather than fix in this tag. The two-line correction already exists on ORPHAN 4895b81 (size_t fee_per_gas_size = msg->has_max_fee_per_gas ? msg->max_fee_per_gas.size : msg->gas_price.size;) and is a clean pickup for the next release; carrying it now buys no security and touches the signing path unnecessarily.
Deferred because 7.14.2 is a minimal security release; this did not clear the bar for a late change. Filed so it is not lost.
Triaged during the 7.14.2 residual pass and deferred out of 7.14.2 as
low. Still present atrelease/7.14.2head.Evidence
lib/firmware/ethereum.c:598 (
if (msg->gas_price.size + msg->gas_limit.size > 30)), display path at lib/firmware/ethereum.c:536-547Assessment
Still present. ethereum.c changed substantially on this branch (the UnknownToken/AdvancedMode gate, the EIP-712 confirmation, the USER_CANCELLED branch) but line 598 is untouched, and ethereum_signing_init still requires only max_fee_per_gas for type 2 (ethereum.c:668-674), so gas_price.size is 0 on that path and the guard degenerates to gas_limit.size > 30. layoutEthereumFee then computes the displayed fee with bn_multiply(&val, &gas, &secp256k1.prime) at ethereum.c:547 — modular, so it wraps rather than saturating. The code defect is real: the guard reads a field the transaction does not use.
I checked the two ways this could escalate and both fail. There is no memory-safety angle: include/keepkey/transport/messages-ethereum.options pins max_fee_per_gas, gas_limit and value at max_size:32, so the
memcpy(pad_val + (32 - len), ...)idiom in formatEthereumFeeEIP1559 (ethereum.c:519-521) and layoutEthereumFee (:543) can never underflow the destination. And the display lie is unreachable: making the product wrap needs max_fee_per_gas * gas_limit >= p, about 1.16e77 wei, while the entire ETH supply is on the order of 1.2e26 wei — and EIP-1559 requires the sender's balance to cover gas_limit * max_fee_per_gas at inclusion, so any parameter set large enough to wrap produces a transaction no node will ever include. For every product a fundable account could pay, the product is far below p and bn_multiply is exact, so the displayed figure is correct. Nothing signed under this defect can move funds.Low, and file rather than fix in this tag. The two-line correction already exists on ORPHAN 4895b81 (
size_t fee_per_gas_size = msg->has_max_fee_per_gas ? msg->max_fee_per_gas.size : msg->gas_price.size;) and is a clean pickup for the next release; carrying it now buys no security and touches the signing path unnecessarily.Deferred because 7.14.2 is a minimal security release; this did not clear the bar for a late change. Filed so it is not lost.