Skip to content

Commit 5e5ba53

Browse files
fix(billing): restrict redirect protocols and guard priceId type
1 parent c3ce208 commit 5e5ba53

1 file changed

Lines changed: 9 additions & 2 deletions

File tree

modules/billing/services/billing.service.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ const isAllowedUrl = (url) => {
2020
const parsed = new URL(url);
2121
const env = process.env.NODE_ENV || 'development';
2222
const allowHttp = env === 'development' || env === 'test';
23-
if (!allowHttp && parsed.protocol !== 'https:') return false;
23+
const allowedProtocols = allowHttp ? ['http:', 'https:'] : ['https:'];
24+
if (!allowedProtocols.includes(parsed.protocol)) return false;
2425
if (config.domain && !allowHttp) {
2526
const configHost = new URL(config.domain.startsWith('http') ? config.domain : `https://${config.domain}`).hostname;
2627
if (parsed.hostname !== configHost) return false;
@@ -48,8 +49,14 @@ const createCheckout = async (organization, priceId, successUrl, cancelUrl) => {
4849
}
4950

5051
// Validate priceId against known active Stripe prices and resolve the canonical plan id
52+
if (typeof priceId !== 'string' || !priceId.trim()) {
53+
throw new Error('Invalid priceId: must be an active published price');
54+
}
5155
const plans = await BillingPlansService.getPlans();
52-
const matchedPlan = plans.find((p) => p.stripePriceMonthly === priceId || p.stripePriceAnnual === priceId);
56+
const matchedPlan = plans.find(
57+
(p) => (p.stripePriceMonthly && p.stripePriceMonthly === priceId)
58+
|| (p.stripePriceAnnual && p.stripePriceAnnual === priceId),
59+
);
5360
if (!matchedPlan) {
5461
throw new Error('Invalid priceId: must be an active published price');
5562
}

0 commit comments

Comments
 (0)