fix: Broken Access Control: Private form access and invoice creation on other stores via unscoped authorization check (#7236)
What changed, and why it matters
This commit fixes a broken access control bug in BTCPay Server's form feature. Previously, when checking whether a user could view a private form, the system asked 'Is this user allowed to view store settings anywhere?' without specifying which store. That meant any user with store-settings permission for any store could see private forms belonging to other stores, and could potentially create invoices against those stores. The patch changes the authorization check to include the specific store ID of the form, so users must have permission for that exact store.
Apply this patch and audit all other authorization calls site-wide for missing resource/store scoping. Review whether the invoice-creation path referenced in the commit title has a corresponding fix, since the diff only covers form viewing.
Security signals we found
Broken Access Control (CWE-284)
Missing authorization scope/resource parameter
Cross-store privilege escalation
Private data disclosure via unscoped permission check
Evidence from the diff
In BTCPayServer/Forms/UIFormsController.cs, two authorization checks for viewing non-public forms were calling _authorizationService.AuthorizeAsync(User, Policies.CanViewStoreSettings) without a resource scope. ASP.NET Core authorization handlers that expect a store-scoped resource would then fall back to a generic permission check, allowing any principal holding CanViewStoreSettings for any store to pass. The patch passes formData.StoreId as the resource, scoping the check to the form’s owning store. The commit title also claims this allowed invoice creation on other stores via the same unscoped check, though the diff itself only shows the form-viewing paths.
Changed components
BTCPayServer/Forms/UIFormsController.csPrivate form viewing endpointsASP.NET Core authorization policy CanViewStoreSettingsInspect captured patch +2 / −2
diff --git a/BTCPayServer/Forms/UIFormsController.cs b/BTCPayServer/Forms/UIFormsController.cs
index 6b5b719..ca95ad1 100644
--- a/BTCPayServer/Forms/UIFormsController.cs
+++ b/BTCPayServer/Forms/UIFormsController.cs
@@ -154,7 +154,7 @@ public class UIFormsController : Controller
}
if (!formData.Public &&
- !(await _authorizationService.AuthorizeAsync(User, Policies.CanViewStoreSettings)).Succeeded)
+ !(await _authorizationService.AuthorizeAsync(User, formData.StoreId, Policies.CanViewStoreSettings)).Succeeded)
{
return NotFound();
}
@@ -192,7 +192,7 @@ public class UIFormsController : Controller
}
if (!formData.Public &&
- !(await _authorizationService.AuthorizeAsync(User, Policies.CanViewStoreSettings)).Succeeded)
+ !(await _authorizationService.AuthorizeAsync(User, formData.StoreId, Policies.CanViewStoreSettings)).Succeeded)
{
return NotFound();
}
Why this scored 74/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.