Security thinking
Model threats and attackers
Describe attacker goals, capabilities, entry points, and abuse cases without trying to predict every possible exploit.
A threat is a believable way an asset can be harmed. We do not need a movie villain or a list of every hacking tool.
A useful threat model answers one question: what can this attacker already do before the attack begins? Start from existing access, not from imagined superpowers.
Name the actors
For a typical web app, the cast is short:
- anonymous visitors, who can reach public pages and endpoints
- signed-in users, with a valid account of their own
- compromised accounts, where the credentials are real but the person behind them is not
- malicious dependencies, pulled in during a build
- insiders, with dashboard or database access
- automated bots, hammering forms and APIs
Give each actor a goal and an entry point. “A signed-in user wants to read other people’s drafts through the notes API” is testable. “Hackers want to hack us” is not.
The most common attacker is ordinary
Here is the scenario that plays out constantly. A signed-in user opens their own note and looks at the request:
GET /api/notes/1842
Cookie: session=eyJhbGciOi...
They change 1842 to 1841 and read another person’s draft. No special tool. The attacker needs only a valid account and a missing ownership check on the server.
This is why threat models become vague when every attacker is “advanced.” Start from the access an ordinary user already has, then add stronger capabilities only when the design supports them.
Write attacker stories
Capture each threat as a short story with four parts:
actor: signed-in user (free tier)
goal: read drafts belonging to other accounts
entry point: GET /api/notes/:id
expected control: server checks note owner against session user
Three of these stories are worth more than a fifty-row spreadsheet nobody reads.
Then test the cheapest one. Create two test accounts, sign in as the first, and request a note owned by the second. Save the request and the result. If data comes back, you found a real weakness before writing any tooling. If you get a denial, keep that evidence too — it proves the expected control exists in the running system.
Lesson completed