💼
VerifiedSimplesilver
Payment Flow Debugger
Debug payment issues, trace checkout flows, and analyze webhook failures in billing systems.
billing
0v1.0.0
Audit billing code for security vulnerabilities, validate inputs, and ensure payment security best practices.
# Billing Security Auditor Skill
Audit billing code for security vulnerabilities, validate inputs, and ensure payment security best practices.
## When to Use This Skill
Use before:
- Deploying payment code to production
- Creating pull requests with billing changes
- Security reviews
- After making any changes to payment endpoints
## Security Checklist
### 1. Input Validation
**Check ALL user inputs are validated**:
✅ `/api/billing/checkout`:
- [ ] `priceId` validated against known price IDs
- [ ] `returnUrl` validated against whitelist
- [ ] No direct use of user input in Stripe API calls
- [ ] All parameters have type checking
✅ `/api/billing/portal`:
- [ ] `returnUrl` validated against whitelist
- [ ] User authentication verified
- [ ] Customer ID retrieved from database, not user input
✅ `/api/webhooks/stripe`:
- [ ] Signature verification BEFORE processing
- [ ] Event type checked in whitelist
- [ ] No SQL injection vectors in metadata
- [ ] Metadata fields sanitized
### 2. Authentication & Authorization
**Every billing endpoint must**:
- [ ] Verify user is authenticated (JWT/session)
- [ ] Verify user owns the subscription (RLS or manual check)
- [ ] Use service role for database writes (not user credentials)
- [ ] Never trust client-side tier/subscription data
**Check RLS policies**:
```sql
-- Users can only SELECT own subscription
SELECT policy_name FROM pg_policies
WHERE tablename = 'subscriptions' AND cmd = 'SELECT';
-- Service role can manage all subscriptions
-- Users CANNOT INSERT/UPDATE/DELETE subscriptions
```
### 3. Secrets Management
**Audit for exposed secrets**:
❌ **Never do this**:
```typescript
// BAD: API key in code
const stripe = new Stripe('sk_live_abc123');
// BAD: Logged to console
console.log('Stripe key:', process.env.STRIPE_SECRET_KEY);
// BAD: Returned to client
return { webhookSecret: process.env.STRIPE_WEBHOOK_SECRET };
```
✅ **Do this**:
```typescript
// GOOD: From environment variable
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
// GOOD: Logged without value
console.log('Stripe configured:', !!process.env.STRIPE_SECRET_KEY);
// GOOD: Never sent to client
// Server-side only
```
**Check for secret leakage**:
```bash
# Search for potential secret exposure
grep -r "STRIPE_SECRET_KEY" src/
grep -r "WEBHOOK_SECRET" src/
grep -r "console.log.*stripe" src/
```
### 4. Injection Attack Prevention
**SQL Injection**:
- [ ] All database queries use parameterized queries
- [ ] No string concatenation in SQL
- [ ] User input never directly in WHERE clauses
**Command Injection**:
- [ ] No dynamic code execution with user input
- [ ] No shell commands with user input
- [ ] All file paths validated
### 5. Rate Limiting & DoS Prevention
**Check rate limits exist**:
- [ ] `/api/billing/checkout` → 5 req/min per user
- [ ] `/api/billing/portal` → 10 req/min per user
- [ ] `/api/webhooks/stripe` → (Stripe handles this)
**Test rate limiting**:
```bash
# Make 6 rapid requests
for i in {1..6}; do
curl -X POST http://localhost:3000/api/billing/checkout \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"priceId":"price_test","returnUrl":"http://localhost:3000/billing"}'
echo "Request $i"
done
# 6th request should return 429
```
### 6. OWASP Top 10 Review
**A01: Broken Access Control**
- [ ] Users can't access other users' subscriptions
- [ ] Users can't modify their own subscription tier directly
- [ ] RLS policies enforce ownership
**A02: Cryptographic Failures**
- [ ] Webhook signatures verified with cryptographic function
- [ ] HTTPS enforced on all endpoints
- [ ] No sensitive data in URLs/query params
**A03: Injection**
- [ ] See section 4 above
**A04: Insecure Design**
- [ ] No security bypasses (e.g., "admin=true" param)
- [ ] Upgrade flow requires payment, can't be bypassed
- [ ] Tier verification on every API request
**A05: Security Misconfiguration**
- [ ] Error messages don't leak stack traces
- [ ] Dev tools (Stripe test mode) not in production
- [ ] Environment variables properly scoped
**A07: Identification & Authentication Failures**
- [ ] Sessions expire appropriately
- [ ] No weak authentication (API keys in URLs)
- [ ] Multi-factor encouraged for high-value accounts
**A08: Software & Data Integrity Failures**
- [ ] Webhook signatures prevent tampering
- [ ] Database constraints enforce data integrity
- [ ] No unsigned webhooks processed
**A09: Security Logging & Monitoring Failures**
- [ ] Failed payment attempts logged
- [ ] Webhook failures logged
- [ ] Unusual activity patterns detectable
**A10: Server-Side Request Forgery (SSRF)**
- [ ] No user-controlled URLs fetched by server
- [ ] Webhook URLs validated (Stripe sends to us, we don't fetch)
### 7. Payment-Specific Security
**PCI Compliance**:
- [ ] No credit card data stored
- [ ] No credit card data logged
- [ ] All payment processing via Stripe (tokenized)
**Webhook Security**:
- [ ] Signature verification before processing
- [ ] Idempotency keys used (prevent duplicate charges)
- [ ] Replay attack prevention (timestamp validation)
**Subscription Manipulation**:
- [ ] Users can't create subscriptions without payment
- [ ] Users can't upgrade tier without checkout
- [ ] Users can't fake webhook events
### 8. Error Handling Security
**Check error messages don't leak info**:
❌ **Bad**:
```typescript
catch (error) {
return NextResponse.json({ error: error.message }, { status: 500 });
// Might leak: "Database connection failed at 192.168.1.5:5432"
}
```
✅ **Good**:
```typescript
catch (error) {
console.error('Checkout error:', error); // Log internally
return NextResponse.json({
error: 'Failed to create checkout session. Please try again.',
code: 'CHECKOUT_ERROR'
}, { status: 500 });
}
```
### 9. Automated Security Scan
Run these commands:
```bash
# Dependency vulnerabilities
npm audit
# TypeScript strict mode (catches some issues)
npm run type-check
# ESLint security plugin
npm run lint
```
### 10. Manual Code Review Checklist
For each file in `/src/app/api/billing/` and `/src/lib/billing/`:
- [ ] Read through line by line
- [ ] Question every user input
- [ ] Verify every database query
- [ ] Check every API call
- [ ] Test error paths
- [ ] Verify auth on every endpoint
## Conclusion
Security is not a checkbox - it's a mindset. Assume attackers will try:
- Forged webhooks
- Price manipulation
- Tier escalation
- Account takeover
- Data exfiltration
Defend accordingly.
Debug payment issues, trace checkout flows, and analyze webhook failures in billing systems.
Handle subscription state changes, tier migrations, cancellations, and edge cases in the billing lifecycle.
Optimize social media engagement through comment strategies and DM automation