Repository navigation
Conversation
The LSPS1 client forwarded the LSP-provided payment options to the caller without checking them. A misbehaving LSP could advertise a small order total while embedding a BOLT11 invoice or BOLT12 offer for a much larger amount, overcharging an application that shows the advertised total to the user and then pays the embedded payment request. We now check that each payment option's total equals the fee plus the requested client balance, and that an embedded invoice or offer asks for exactly that total, as bLIP-51 requires. Inconsistent responses are rejected and the pending request fails. Reported by Project Loupe. Co-Authored-By: HAL 9000
|
I've assigned @TheBlueMatt as a reviewer! |
|
|
||
| if let Some(bolt11) = payment.bolt11.as_ref() { | ||
| if !totals_match(bolt11.fee_total_sat, bolt11.order_total_sat) | ||
| || bolt11.invoice.amount_milli_satoshis() != total_msat(bolt11.order_total_sat) |
There was a problem hiding this comment.
One edge case: if order_total_sat * 1000 overflows, total_msat returns None. If the invoice is also amountless, the comparison becomes None != None, which is false, so the check passes unexpectedly. The same issue applies to BOLT12 offers without a fixed amount.
This is unlikely to happen in practice, but it weakens the guarantee that the embedded payment request matches the exact total.
Could we reject the case when total_msat is None, or require both values to be Some before comparing? A regression test with an amountless invoice would help cover this
The LSPS1 client forwarded the LSP-provided payment options to the caller without checking them. A misbehaving LSP could advertise a small order total while embedding a BOLT11 invoice or BOLT12 offer for a much larger amount, overcharging an application that shows the advertised total to the user and then pays the embedded payment request.
We now check that each payment option's total equals the fee plus the requested client balance, and that an embedded invoice or offer asks for exactly that total, as bLIP-51 requires. Inconsistent responses are rejected and the pending request fails.
Reported by Project Loupe.
Co-Authored-By: HAL 9000