What changed, and why it matters
This commit fixes a bug in BTCPay Server's LNURL feature for pull payments. Previously, if someone requested a LNURL for a pull payment that didn't exist, the code would try to use a null (empty) pull payment object, which could cause the server to crash or behave unpredictably instead of returning a simple 'not found' error. The fix adds a check to return 'not found' if the pull payment is missing.
Treat as a low-to-moderate reliability/security fix. Verify whether the null dereference was reachable by unauthenticated users and whether it caused an exception or a 500 response. Review adjacent LNURL/payout endpoints for similar missing null checks. No immediate emergency response is indicated by this single-line patch alone.
Security signals we found
Null dereference / missing null check on database/service lookup result
Potential server-side exception (DoS/crash) on crafted LNURL request
Information disclosure risk if exception details leak stack traces
No authentication/authorization change in this diff
Evidence from the diff
In UILNURLController.cs, GetLNURLForPullPayment previously called pp.IsRunning() and pp.IsSupported() without first checking if pp was null after _pullPaymentHostedService.GetPullPayment returned. This is a null dereference bug. The patch adds ‘pp is null ||’ to the guard clause so the method returns NotFound() when the pull payment does not exist. The crash/behavior depends on whether GetPullPayment can return null for invalid or deleted pull payment IDs.
Changed components
BTCPayServer/Controllers/UILNURLController.csLNURL pull payment endpoint (GetLNURLForPullPayment)Inspect captured patch +1 / −1
### BTCPayServer/Controllers/UILNURLController.cs
@@ -119,7 +119,7 @@ internal async Task<IActionResult> GetLNURLForPullPayment(string cryptoCode, str
var pmi = PayoutTypes.LN.GetPayoutMethodId(cryptoCode);
var paymentMethodId = PaymentTypes.LN.GetPaymentMethodId(cryptoCode);
var pp = await _pullPaymentHostedService.GetPullPayment(pullPaymentId, true);
- if (!pp.IsRunning() || !pp.IsSupported(pmi) || !_payoutHandlers.TryGetValue(pmi, out var payoutHandler))
+ if (pp is null || !pp.IsRunning() || !pp.IsSupported(pmi) || !_payoutHandlers.TryGetValue(pmi, out var payoutHandler))
{
return NotFound();
}Why this scored 46/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.