A threat model in 15 minutes
What you protect, from whom, with what.
Before you defend against anything, write down what you're protecting, from whom, and how badly each thing matters. That is a threat model. It takes 15 minutes, costs nothing, and is the single highest-leverage security activity for a small team.
What a threat model answers
- What are we protecting? User data? Payment info? Source code? IP?
- From whom? Script kiddies? Competitors? Disgruntled employees? Nation-states?
- What are we willing to spend? A hobby project and a fintech have very different budgets.
- What's the worst case? A data leak embarrasses you; a payment leak ends you.
STRIDE — the canonical mental model
STRIDE categories
For each endpoint in your API, ask: which letters apply? Most endpoints have a few. A login endpoint cares about S, I, D. A notes endpoint cares about T, I, E. Knowing which letter applies focuses your defence.
The shape of the document
A threat model doesn't need to be a 50-page Word doc. Yours can be a single Markdown file. Three sections:
1. Assets — what you protect
- User accounts (email, password hash, profile)
- Tenant data (orders, notes, files)
- Payment info (last 4, never the full card)
- Admin access
- Service availability
2. Actors — who you protect against
- Anonymous user (public internet)
- Authenticated regular user (logged in)
- Authenticated user trying to access another user's data
- Compromised admin account
- Insider (developer, employee)
3. Threats — what could go wrong
One line per threat. Be specific. Map each to STRIDE.
- T1 (I, T): A logged-in user PATCHes another user's note by guessing the ID. (IDOR)
- T2 (S): An attacker uses a leaked JWT secret to forge tokens for any user.
- T3 (D): Bot floods /api/auth/login with brute force; password reset queue grows; legit users locked out.
- T4 (E): SQL injection on a search endpoint exfiltrates the users table.
- T5 (I): Public bucket lets anyone download customer uploads.
Risk = likelihood × impact
Rate each threat 1-5 on likelihood and 1-5 on impact. Multiply. Sort. Spend your time on the top half. Ignore the bottom half for now.
Don't obsess over precision. The point is forcing yourself to compare threats so you don't spend a week on a 1×1 threat while a 5×5 sits unhandled.
The smallest model that's useful
For a small team / solo founder, a useful threat model fits on one page:
- 5 assets
- 5 actors
- 10 threats, ranked
- The top 3 actively being mitigated
Anything more is overkill until you have customer/regulatory pressure for one.
When to revisit
- You launched a major feature (new endpoints, new data).
- You added a new third-party service (more attack surface).
- You had a security incident or scare.
- It's been > 6 months and you haven't looked.
Quick check
Try it
Write a threat model for your own Grit API:
- Create
SECURITY.mdat your repo root. - List 5 assets you protect (be specific to YOUR product).
- List 5 actors.
- List 10 threats — one per STRIDE category at minimum. Rate likelihood (1-5) × impact (1-5).
- Sort. Underline the top 3.
- For each of the top 3, write 1 sentence on the planned mitigation.
What's next
Next lesson — OWASP Top 10 tour. One sentence per category, mapped to real Grit endpoints. Then we attack IDOR in chapter 2.
Spot a typo? Have an idea?
Help us improve this lesson. One click opens a GitHub issue with the lesson URL pre-filled — suggest clearer wording, report a bug, or request more depth. The course keeps improving thanks to learners like you.
Suggest an improvement on GitHub