Pass store to payment method config validation (#7513)
What changed, and why it matters
This commit changes how BTCPay Server validates payment method settings so that the store object is passed into the validation process. The change itself only adds a new piece of information (the store) to validation contexts; it does not by itself fix a visible bug or block an attack. Without the rest of the related code, it is unclear whether this prevents a security issue or is just a refactoring/cleanup step.
Treat as a routine code change unless paired with another commit that actually uses Store in validation. Review the related PR #7513 and any follow-up commits to see whether store-based authorization or configuration checks were added. If this is part of a security fix, the missing validation logic should be identified and deployed together with this change.
Security signals we found
Validation context now receives store-scoped data, which can be used for authorization decisions
Touches payment-method configuration endpoints (on-chain and Lightning)
No explicit security claim or CVE reference in commit message
Evidence from the diff
The patch updates PaymentMethodConfigValidationContext to require a Data.StoreData parameter and threads the current Store/store object through three call sites: GreenfieldStorePaymentMethodsController, UIStoresController.LightningLike, and GreenfieldStoreOnChainPaymentMethodsController. The change gives payment-method validation logic access to store-level data, which could enable permission or configuration checks that depend on store properties. The diff does not show any new validation rules being enforced, only the plumbing needed to make the store available.
Changed components
BTCPayServer/Controllers/GreenField/GreenfieldStorePaymentMethodsController.csBTCPayServer/Controllers/UIStoresController.LightningLike.csBTCPayServer/Payments/IPaymentMethodHandler.csBTCPayServer/Plugins/Wallets/Controllers/GreenfieldStoreOnChainPaymentMethodsController.csInspect captured patch +6 / −4
### BTCPayServer/Controllers/GreenField/GreenfieldStorePaymentMethodsController.cs
@@ -81,7 +81,7 @@ public async Task<IActionResult> UpdateStorePaymentMethod(
{
try
{
- var ctx = new PaymentMethodConfigValidationContext(authorizationService, ModelState, config, User, Store.GetPaymentMethodConfig(paymentMethodId));
+ var ctx = new PaymentMethodConfigValidationContext(authorizationService, ModelState, config, User, Store.GetPaymentMethodConfig(paymentMethodId), Store);
await handler.ValidatePaymentMethodConfig(ctx);
config = ctx.Config;
if (ctx.MissingPermission is not null)
### BTCPayServer/Controllers/UIStoresController.LightningLike.cs
@@ -170,7 +170,7 @@ public async Task<IActionResult> SetupLightningNode(string storeId, LightningNod
var handler = (LightningLikePaymentHandler)_handlers[paymentMethodId];
var ctx = new PaymentMethodConfigValidationContext(_authorizationService, ModelState,
- JToken.FromObject(paymentMethod, handler.Serializer), User, oldConf is null ? null : JToken.FromObject(oldConf, handler.Serializer));
+ JToken.FromObject(paymentMethod, handler.Serializer), User, oldConf is null ? null : JToken.FromObject(oldConf, handler.Serializer), store);
await handler.ValidatePaymentMethodConfig(ctx);
if (ctx.MissingPermission is not null)
ModelState.AddModelError(nameof(vm.ConnectionString), StringLocalizer["You do not have the permissions to change this settings"]);
### BTCPayServer/Payments/IPaymentMethodHandler.cs
@@ -76,15 +76,17 @@ void StripDetailsForNonOwner(object details) { }
public class PaymentMethodConfigValidationContext
{
public record MissingPermissionError(string Permission, string Message);
- public PaymentMethodConfigValidationContext(IAuthorizationService authorizationService, ModelStateDictionary modelState, JToken config, ClaimsPrincipal user, JToken? previousConfig)
+ public PaymentMethodConfigValidationContext(IAuthorizationService authorizationService, ModelStateDictionary modelState, JToken config, ClaimsPrincipal user, JToken? previousConfig, Data.StoreData store)
{
PreviousConfig = previousConfig;
ModelState = modelState;
AuthorizationService = authorizationService;
Config = config;
User = user;
+ Store = store;
}
public ClaimsPrincipal User { get; }
+ public Data.StoreData Store { get; }
public JToken? PreviousConfig { get; }
public JToken Config { get; set; }
public ModelStateDictionary ModelState { get; }
### BTCPayServer/Plugins/Wallets/Controllers/GreenfieldStoreOnChainPaymentMethodsController.cs
@@ -84,7 +84,7 @@ public async Task<IActionResult> GetProposedOnChainPaymentMethodPreview(
AssertCryptoCodeWallet(paymentMethodId, out var network, out _);
var handler = handlers.GetBitcoinHandler(network);
- var ctx = new PaymentMethodConfigValidationContext(authorizationService, ModelState, request.Config, User, Store.GetPaymentMethodConfig(paymentMethodId));
+ var ctx = new PaymentMethodConfigValidationContext(authorizationService, ModelState, request.Config, User, Store.GetPaymentMethodConfig(paymentMethodId), Store);
await handler.ValidatePaymentMethodConfig(ctx);
if (ctx.MissingPermission is not null)
{Why this scored 25/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.