Web payments platform (Django + React SPA)
Multi-tenant Django backend serving a React SPA. Orders/payments flow through Stripe; webhooks signed at the edge. Postgres for state, Redis for queues, S3 for receipts.
Username + password, JWT-signed sessions, optional TOTP.
Per-tenant role (owner/admin/manager/member) + cross-tenant Acme admin.
Unauthenticated traffic from the public internet (including bots).
Customer-organization administrator with org-level write privileges.
Regular employee account scoped to their tenant.
External Stripe service posting payment-state changes.
Acme staff with cross-tenant admin tooling.
TLS-terminating reverse proxy in front of the Django app.
gunicorn workers behind nginx; receives proxied requests.
pgbouncer-fronted database access.
| Pri | Name | Actor | Target |
|---|---|---|---|
P0 | Forged Stripe webhook | Anonymous web visitor | Order ledger |
P0 | IDOR on order export | Tenant member | Order ledger |
P1 | Stored XSS in admin notes | Tenant member | Customer PII |
P2 | Credential stuffing via login | Anonymous web visitor | Tenant accounts |
The core attack surface is the Django web tier: login, payment webhooks, admin tooling, and the public order API. The webhook signing path is the highest-impact target — a forged event can mark orders paid. Admin tooling has multiple authorisation gaps (IDOR + XSS), and the login endpoint lacks a rate limit. The codebase also commits a real webhook secret and a stale fixture of real customer data, which broaden the attack surface beyond the live network.