@1440000bytes (aka floppy) is at it again with a very interesting discovery in Cashu mints that run nutshell: when paying out of a lightning gateway, it is possible that an attacker could set exorbitant fees which the mint will pay out of its own balance and not charge the mint user for. The result is that the mints funds could be drained, especially if the attacker is requesting the mint pay out to a lightning node the attacker controls.
Cashu mints quote afee_reserveto the wallet at melt time, and the wallet escrows proofs worthamount + fee_reserve. The mint is then expected to bind thatfee_reserveas an upper limit on what its lightning backend will spend.
Nutshell'sLNbitsWallet.pay_invoice()ignores thefee_limit_msatargument and sends the bolt11 to the LNbits HTTP API with no cap field. Whatever fee LNbits pays up to its ownLNBITS_RESERVE_FEE_PERCENTcomes silently out of the mint operator's own funds that swallows negative-overpayment as alogger.error()and returns successfully.
Ifoverpaid_feeis negative i.e. the backend spent more than the wallet escrowed, the mint logs an error and returns an empty list of change. It does not unwind, it does not raise, it does not refuse the spend. The melt is recorded as successful. The proofs are marked spent. The mint operator’s lightning balance is short by exactlyfee_paid − fee_providedwith no entry in the ledger to recover it.
It looks like nutshell is resolving this by removing LNbits, but mint operators could take the following actions:
Close the gap between the mint’s quotedfee_reserveand the backend’s own cap. Concretely, for operators currently running withLIGHTNING_FEE_PERCENT=0andLIGHTNING_RESERVE_FEE_MIN=0:
- Raise
LIGHTNING_FEE_PERCENTto at or above the backend’s own cap (for LNbits, that meansLIGHTNING_FEE_PERCENT >= LNBITS_RESERVE_FEE_PERCENT, i.e. at least 1.0 with default LNbits). This forces the wallet to escrow at least as much as the backend can ever pay, sooverpaid_feecannot go negative. Wallets may pay slightly more for melts; legitimate users get the excess returned as NUT-08 change.- Set
LIGHTNING_RESERVE_FEE_MINto at least 2000 msat so small melts still have a floor (1% of a 100-sat melt is 1 sat = below msat precision).- For LNbits backends, also lowering
LNBITS_RESERVE_FEE_PERCENTreduces the amount per melt the attacker can drain, but does not close the bug and only raising the mint quote does.- Monitor
mint.logforOverpaid fee is negativelines. Any occurrence is a fund loss event and indicates active exploitation or an unhealthy backend.
floppy wrote a demo of the exploit which you can find here.
Rug the spaaaaammers!!
Ouch. Ignoring
fee_limit_msatbasically turns the mint into a fee sponsor for the route.Curious how many mints were running LNbits with
LIGHTNING_FEE_PERCENT=0