What changed, and why it matters
This commit adds a missing safety check in the API key authorization flow. Previously, if a user clicked a 'confirm' action for an API key that no longer existed, the code would try to use a null (non-existent) key object, which could cause a server crash or unexpected behavior. Now the code checks whether the key exists first and shows an error message if it doesn't.
Deploy the patch. Review related authorization endpoints for similar missing null checks on repository return values. Consider adding automated tests covering the 'confirm' path with a deleted or invalid API key.
Security signals we found
Null dereference / NullReferenceException prevented
Missing validation of repository return value
User-facing authorization flow hardening
Potential denial-of-service or error-condition information disclosure via unhandled exception
Evidence from the diff
In UIManageController.APIKeys.cs, the AuthorizeAPIKey action handles both ‘authorize’ (create new key) and ‘confirm’ (retrieve existing key by ApiKey) commands. When command is ‘confirm’, _apiKeyRepository.GetKey() can return null if the key has been deleted or is invalid. The original code immediately dereferenced key with key.Key ??= viewModel.ApiKey without null-checking. The patch adds a null check: if key is null, it sets an error status message and redirects to the APIKeys list. This prevents a NullReferenceException and provides graceful failure handling.
Changed components
BTCPayServer/Controllers/UIManageController.APIKeys.csAPI key authorization/confirmation endpointInspect captured patch +9 / −0
### BTCPayServer/Controllers/UIManageController.APIKeys.cs
@@ -221,6 +221,15 @@ public async Task<IActionResult> AuthorizeAPIKey([FromForm] AuthorizeApiKeysView
var key = command == "authorize"
? await CreateKey(viewModel, (viewModel.ApplicationIdentifier, viewModel.RedirectUrl?.AbsoluteUri))
: await _apiKeyRepository.GetKey(new APIKeyRepository.Selector.ByApiKey(viewModel.ApiKey));
+ if (key is null)
+ {
+ TempData.SetStatusMessageModel(new StatusMessageModel
+ {
+ Severity = StatusMessageModel.StatusSeverity.Error,
+ Message = StringLocalizer["The API key was not found"].Value
+ });
+ return RedirectToAction("APIKeys");
+ }
key.Key ??= viewModel.ApiKey;
if (viewModel.RedirectUrl != null)Why this scored 58/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.