Skip to content

Commit ec062ab

Browse files
ardalisclaude
andcommitted
Fix XSS/loop/webhook findings from Manage Subscriptions review
- Remove member-controlled data (CustomerEmail, subscription Id) from onsubmit confirm() JS strings in ManageSubscriptions/Index.cshtml. Razor HTML-encoding is decoded by the HTML parser before the JS engine sees it, so a literal apostrophe (e.g. o'brien@example.com) reached the JS string context, silently skipping confirmation (including for irreversible Cancel Now) or enabling stored XSS in the admin session. Confirm messages are now static. - Fix CustomerSubscriptionUpdatedWebHook comparing stripeEvent.Type against EventTypes.CustomerUpdated ("customer.updated") instead of EventTypes.CustomerSubscriptionUpdated ("customer.subscription.updated"), which made the endpoint reject every real event it receives with an uncaught 500. - Harden StripeSubscriptionHandlerService.ListBillableAsync's pagination loop against an infinite loop if Stripe ever returns HasMore=true with an empty Data page. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent e5df5c2 commit ec062ab

3 files changed

Lines changed: 5 additions & 5 deletions

File tree

src/DevBetterWeb.Infrastructure/SubscriptionHandler/StripeSubscriptionHandler/StripeSubscriptionHandlerService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public async Task<List<Subscription>> ListBillableAsync(CancellationToken cancel
3535
{
3636
options.StartingAfter = page.Data[^1].Id;
3737
}
38-
} while (page.HasMore);
38+
} while (page.HasMore && page.Data.Count > 0);
3939

4040
return subscriptions.Where(s => _billableStatuses.Contains(s.Status)).ToList();
4141
}

src/DevBetterWeb.Web/Endpoints/StripeWebhookEndpoints/CustomerSubscriptionUpdatedWebHook.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public override async Task<ActionResult> HandleAsync(CancellationToken cancellat
5757

5858
_logger.LogInformation($"Processing Stripe Event Type: {stripeEvent.Type}");
5959

60-
if (stripeEvent.Type != EventTypes.CustomerUpdated)
60+
if (stripeEvent.Type != EventTypes.CustomerSubscriptionUpdated)
6161
{
6262
throw new Exception($"Unhandled Stripe event type {stripeEvent.Type}");
6363
}

src/DevBetterWeb.Web/Pages/Admin/ManageSubscriptions/Index.cshtml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,21 +60,21 @@
6060
else
6161
{
6262
<form method="post" asp-page-handler="Pause" style="display:inline"
63-
onsubmit="return confirm('Pause collection for @subscription.CustomerEmail? Stripe will stop charging until resumed.');">
63+
onsubmit="return confirm('Pause collection for this customer? Stripe will stop charging until resumed.');">
6464
<input type="hidden" name="subscriptionId" value="@subscription.Id" />
6565
<button type="submit" class="btn btn-sm btn-warning">Pause</button>
6666
</form>
6767
}
6868
@if (!subscription.CancelAtPeriodEnd)
6969
{
7070
<form method="post" asp-page-handler="Cancel" style="display:inline"
71-
onsubmit="return confirm('Cancel @subscription.CustomerEmail at period end?');">
71+
onsubmit="return confirm('Cancel this subscription at period end?');">
7272
<input type="hidden" name="subscriptionId" value="@subscription.Id" />
7373
<button type="submit" class="btn btn-sm btn-outline-danger">Cancel at Period End</button>
7474
</form>
7575
}
7676
<form method="post" asp-page-handler="CancelNow" style="display:inline"
77-
onsubmit="return confirm('IMMEDIATELY cancel @subscription.Id for @subscription.CustomerEmail? This cannot be undone.');">
77+
onsubmit="return confirm('IMMEDIATELY cancel this subscription? This cannot be undone.');">
7878
<input type="hidden" name="subscriptionId" value="@subscription.Id" />
7979
<button type="submit" class="btn btn-sm btn-danger">Cancel Now</button>
8080
</form>

0 commit comments

Comments
 (0)