Sample Audit Report
Demo data · target: app.example-saas.com · illustrative findings, not a real customer
[CRITICAL] State-Machine Intent Desync in Checkout
POST /api/plans/select · Impact: Permanent Pro-Tier access without settlement ($0 spent)
The checkout initialization endpoint upgraded the user plan store on initial intent before payment confirmation. Abandoning Stripe checkout left the user with unrestricted Pro benefits indefinitely.
curl -X POST https://target.com/api/plans/select -H 'Authorization: Bearer <GUEST_JWT>' -d '{"tier":"pro"}'
# User immediately granted Pro limits before Stripe webhook fired// Gated to Stripe checkout.session.completed webhook:
if (event.type === 'checkout.session.completed' && session.payment_status === 'paid') {
await planStore.set(session.metadata.userId, session.metadata.tier);
}[HIGH] Unauthenticated IDOR in Resource Deletion
DELETE /api/watches/[id] · Impact: Arbitrary deletion of any customer monitored target
The delete route omitted authentication and tenant validation, executing store.delete(id) on any raw UUID provided in the path without checking ownership.
curl -X DELETE https://target.com/api/watches/target-uuid-1234 # HTTP/2 200 OK — Resource purged with zero auth headers
const profile = await currentUserProfile();
if (!profile) return NextResponse.json({ error: 'Auth required' }, { status: 401 });
const item = await store.get(params.id);
if (item.userId !== profile.userId) return NextResponse.json({ error: 'Not found' }, { status: 404 });[HIGH] Unscoped Customer PII & Stripe Session Leak
GET /api/orders · Impact: Exfiltration of buyer emails and live Stripe session IDs
Orders query failed to scope results to the active session owner, broadcasting all recent platform transactions and customer email addresses unauthenticated.
curl -s https://target.com/api/orders | jq . # Returns full customer list with raw buyer emails & payment identifiers
const scoped = orders.filter((o) => o.buyer === profile.userId || o.buyer === profile.email);
return NextResponse.json({ orders: scoped.map(o => ({ ...o, stripeSessionId: null })) });