Threat Modeling & Abuse Prevention
You can’t secure a system you haven’t reasoned about. Threat modeling is the discipline of asking, before you ship: who would attack this, what are they after, where are the weak points, and what do we do about each? It turns security from a vague worry into a checklist tied to your actual design.
Trust boundaries: the core concept
Section titled “Trust boundaries: the core concept”A trust boundary is any line where data crosses from a less-trusted zone to a more-trusted one — and it’s exactly where attacks happen.
[ user's browser ] ──trust boundary──► [ your API ] ──trust boundary──► [ your database ] untrusted input VALIDATE internal PARAMETERIZE queriesThe rule that follows: never trust input that crossed a boundary. Validate and sanitize at every crossing. The classic failures — SQL injection, XSS — are all “trusted some input that came from an untrusted zone.” Drawing the boundaries on your architecture diagram is step one of any threat model.
STRIDE: a checklist for “what could go wrong”
Section titled “STRIDE: a checklist for “what could go wrong””STRIDE is a mnemonic that prompts you to consider six categories of threat at each component and boundary:
| Threat | Question | Defense (examples) |
|---|---|---|
| Spoofing | Can someone pretend to be another identity? | Authentication, MFA |
| Tampering | Can data be modified in transit/at rest? | Encryption & TLS, signatures |
| Repudiation | Can someone deny an action they took? | Audit logging, signed records |
| Information disclosure | Can data leak? | Encryption, least-privilege authorization |
| Denial of service | Can it be overwhelmed? | Rate limiting, autoscaling, CDN |
| Elevation of privilege | Can a user gain rights they shouldn’t? | Authorization checks, sandboxing |
Walk each component through these six and you’ll surface most realistic threats systematically rather than hoping you thought of everything.
A worked threat model: the password-reset endpoint
Section titled “A worked threat model: the password-reset endpoint”Checklists click once you actually run one. Take POST /password-reset — a deceptively dangerous
endpoint — and walk it across its trust boundary:
[ anyone ]──trust boundary──►[ reset API ]──►[ email service ] [ user DB ] submits an email generates a token, emails a reset linkNow run STRIDE against that one boundary:
| STRIDE | Concrete threat here | Mitigation that falls out |
|---|---|---|
| Spoofing | Request a reset for someone else’s email | Token sent only to the registered address |
| Tampering | Guess or alter the reset token | Long, random, single-use token; server-side check |
| Repudiation | ”I never requested this” | Log every request with IP + timestamp |
| Info disclosure | Different response for real vs unknown email → account enumeration | Identical response and timing either way |
| DoS | Flood resets to spam a victim / burn email quota | Rate-limit per email and per IP |
| Elevation | Old link still works → account takeover | Short TTL, invalidate token on use |
The payoff: those mitigations weren’t memorized — they fell out of running one method against one boundary. That is what threat modeling actually buys you.
Validate input — relentlessly
Section titled “Validate input — relentlessly”Most application-layer compromises trace back to trusting input:
- SQL injection → use parameterized queries, never string-concatenated SQL (see Transactions & ACID’s data layer).
- XSS → escape/encode output, use Content Security Policy.
- Oversized / malformed payloads → enforce size and schema limits at the edge.
The principle is uniform: allowlist what’s valid, reject everything else — far safer than trying to blocklist every bad pattern.
DoS, DDoS, and abuse
Section titled “DoS, DDoS, and abuse”A Denial-of-Service attack tries to exhaust a resource (CPU, connections, bandwidth, a database connection pool) so legitimate users can’t get through. Distributed DoS does it from many sources at once. Layered defenses:
[ Anycast / CDN / scrubbing ] absorb volumetric floods at the edge (far from origin) │[ Rate limiting / WAF ] cap per-client request rate; block known-bad patterns │[ Autoscaling + load shedding ] grow under load; shed excess to protect the core │[ Your service ] smallest, last line — never the firstTwo very different DDoS shapes need different defenses:
- Volumetric (Gbps–Tbps of junk — UDP/amplification floods): absorbed at the edge by Anycast + scrubbing capacity larger than the attacker’s. Your origin never sees it.
- Application-layer (L7): low volume but expensive requests (a search scanning millions of rows, a costly report endpoint). A CDN won’t catch these — they look like real traffic — so you defend with per-endpoint rate limits, query budgets, and shedding the most expensive paths first.
Rate limiting is the workhorse for abuse (credential stuffing, scraping, brute force) as well as DoS — it caps how fast any one actor can act. Pair it with graceful degradation and load shedding so an overload sheds the excess instead of collapsing entirely.
Credential stuffing is the most common login abuse and worth understanding mechanically: attackers replay username/password pairs leaked from other breaches, betting on password reuse. Rate limiting alone is weak (the attack is spread across many IPs and accounts), so you layer defenses — breached-password checks, device fingerprinting, MFA, and login-velocity anomaly detection. A WAF matches request signatures but can’t tell that a perfectly valid-looking login is fraudulent — which is exactly why abuse defense is layered, not a single appliance.
Defense in depth
Section titled “Defense in depth”No single control is enough; assume each layer can fail and stack independent defenses (network → edge → app → data). The goal is that breaching one layer doesn’t hand over the system — it just forces the attacker to defeat the next one.
The thread
Section titled “The thread”What does this buy us, and what does it cost? Threat modeling and abuse prevention cost design time, some latency (validation, rate-limit checks), and infrastructure (WAF, scrubbing). They buy a system whose failure modes you’ve anticipated rather than discovered in an incident. Security is fundamentally about trust boundaries and least privilege — decide explicitly what you trust, verify everything that crosses a line, and limit what any one breach can reach.
Check your understanding
Section titled “Check your understanding”- What is a trust boundary, and what universal rule applies at every one?
- Name the six STRIDE categories and give a defense for any three.
- Why is allowlisting valid input safer than blocklisting bad input?
- Describe the layered defenses against a DDoS attack, from edge to origin.
- Why should you design as if clients will misbehave even absent a malicious attacker?