Fix open redirect in Stripe customer portal returnUrl (FRE-5399)
- Add isValidReturnUrl validation at route level for fast rejection - Add defense-in-depth validation in BillingService.createCustomerPortalSession - Fix isValidReturnUrl bug: origin comparison was never reached due to incorrect protocol check, allowing substring attacks (e.g., app.shieldai.com.evil.com) - Export isValidReturnUrl from shared-billing package index - Add unit tests for all attack vectors Files changed: - packages/api/src/routes/subscription.routes.ts - packages/shared-billing/src/services/billing.service.ts - packages/shared-billing/src/config/billing.config.ts - packages/shared-billing/src/index.ts - packages/shared-billing/src/__tests__/billing.config.test.ts
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { FastifyInstance } from 'fastify';
|
||||
import { BillingService } from '@shieldai/shared-billing/src/services/billing.service';
|
||||
import { SubscriptionService, customerService, webhookService } from '@shieldai/shared-billing/src/services/billing.services';
|
||||
import { SubscriptionTier } from '@shieldai/shared-billing/src/config/billing.config';
|
||||
import { SubscriptionTier, isValidReturnUrl } from '@shieldai/shared-billing/src/config/billing.config';
|
||||
import { AuthRequest } from './auth.middleware';
|
||||
|
||||
const billingService = BillingService.getInstance();
|
||||
@@ -218,6 +218,13 @@ export async function subscriptionRoutes(fastify: FastifyInstance) {
|
||||
});
|
||||
}
|
||||
|
||||
if (!isValidReturnUrl(returnUrl)) {
|
||||
return reply.status(400).send({
|
||||
error: 'Invalid return URL',
|
||||
message: 'returnUrl must be from an allowed origin',
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
const portalSession = await billingService.createCustomerPortalSession(
|
||||
customerId,
|
||||
|
||||
Reference in New Issue
Block a user