security: Address critical security vulnerabilities and improve code quality

🔒 Security Fixes:
- Make webhook signature validation required for production
- Prevent information disclosure by returning 200 for all webhook responses
- Sanitize external error messages while preserving internal logging

🔧 Code Quality Improvements:
- Add URL validation to prevent localhost usage in production
- Create currency utilities for proper handling of non-centesimal currencies
- Replace unsafe 'any' types with type-safe ProviderData wrapper
- Add comprehensive input validation for amounts, currencies, and descriptions
- Set default Stripe API version for consistency

📦 New Features:
- Currency conversion utilities supporting JPY, KRW, and other special cases
- Type-safe provider data structure with metadata
- Enhanced validation functions for payment data

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-09-17 18:38:44 +02:00
parent 209b683a8a
commit bf9940924c
6 changed files with 197 additions and 21 deletions

View File

@@ -6,13 +6,18 @@ import { extractSlug } from '@/plugin/utils'
/**
* Common webhook response utilities
* Note: Always return 200 for webhook acknowledgment to prevent information disclosure
*/
export const webhookResponses = {
success: () => Response.json({ received: true }, { status: 200 }),
error: (message: string, status = 400) => Response.json({ error: message }, { status }),
missingBody: () => Response.json({ error: 'Missing request body' }, { status: 400 }),
paymentNotFound: () => Response.json({ error: 'Payment not found' }, { status: 404 }),
invalidPayload: () => Response.json({ error: 'Invalid webhook payload' }, { status: 400 }),
error: (message: string, status = 400) => {
// Log error internally but don't expose details
console.error('[Webhook] Error:', message)
return Response.json({ error: 'Invalid request' }, { status })
},
missingBody: () => Response.json({ received: true }, { status: 200 }),
paymentNotFound: () => Response.json({ received: true }, { status: 200 }),
invalidPayload: () => Response.json({ received: true }, { status: 200 }),
}
/**
@@ -95,12 +100,14 @@ export function handleWebhookError(
const message = error instanceof Error ? error.message : 'Unknown error'
const fullContext = context ? `[${provider} Webhook - ${context}]` : `[${provider} Webhook]`
// Log detailed error internally for debugging
console.error(`${fullContext} Error:`, error)
// Return generic response to avoid information disclosure
return Response.json({
error: 'Webhook processing failed',
details: message
}, { status: 500 })
received: false,
error: 'Processing error'
}, { status: 200 })
}
/**