Insecure Design
OWASP Top 10
Course 1 · Chapter 4 · A04: Insecure Design
Every category so far has had a concrete fix you can write in code: parameterize the query, hash the password, check ownership. A04 Insecure Design is different in kind — it's about flaws baked into the design itself, where no amount of perfect code can save you because the very thing being built is unsafe. It's the newest category (added in 2021) and arguably the most important shift in how the Top 10 thinks.
A04: Insecure Design — The Category About What You Build
The crucial distinction this category introduces: insecure design vs insecure implementation.
| Implementation flaw | Design flaw (A04) | |
|---|---|---|
| What's wrong | the code does the right thing wrong | the right thing to do was never specified |
| Example | a query that should be parameterized isn't | no rate limit was ever designed for password reset |
| Fixable in code? | yes — fix the line | no — the missing control must be designed in |
What Insecure Design Looks Like
- Missing controls by design — no rate limiting on login/reset (enabling brute force/stuffing), no limits on a costly operation, no anti-automation on a high-value action.
- Trusting the client for business logic — a checkout that takes the price from the request, a "is premium user" flag sent by the browser; the design assumed the client wouldn't lie.
- Business-logic flaws — workflows that can be done out of order or abused: applying a discount code unlimited times, refunding more than was paid, skipping a payment step, negative quantities.
- No defence against abuse of legitimate features — a coupon system with no per-user cap, a referral program that can be farmed, an API with no quotas.
- Over-collection / over-exposure of data — designing to store or return more sensitive data than the feature needs.
The Core Practice: Threat Modeling
The primary defence against insecure design is threat modeling — thinking, during design, about what could go wrong and who might attack the feature, before a line is written. A lightweight version asks four questions (the Shostack framework):
- What are we building? — a clear picture of the feature, its data, and its trust boundaries (where data crosses from untrusted to trusted).
- What can go wrong? — brainstorm threats (a useful mnemonic is STRIDE: Spoofing, Tampering, Repudiation, Information disclosure, Denial of service, Elevation of privilege).
- What are we going to do about it? — decide which controls to design in (rate limits, server-side validation, authorization checks, abuse caps).
- Did we do a good job? — review and validate the design against the threats.
The payoff is leverage: a control identified at design time is cheap; the same control retrofitted after a breach is expensive and often patchy. A04 essentially says "do this."
Secure-by-Design Principles
A04 promotes a set of design-time principles — most of which you've already met as the reasons behind earlier defences:
- Least privilege — components and users get the minimum access needed (A01, A02 key management).
- Defence in depth — layered controls so one failure isn't catastrophic (the theme of every security course).
- Fail securely — on error, default to denying access, not allowing it (deny-by-default, A01).
- Secure defaults — the out-of-the-box configuration is the safe one (links to A05).
- Minimize attack surface — don't build/expose features and data you don't need.
- Separation of duties & trust boundaries — be explicit about what is trusted and validate everything crossing a boundary.
Hands-On Exercises
For each, decide whether it's an insecure implementation or an insecure design, and justify: (a) a SQL query that forgot to parameterize; (b) a password reset that uses "mother's maiden name"; (c) a checkout that trusts the client-sent price; (d) a session cookie missing the HttpOnly flag. Explain why the design ones can't be fixed by better code alone.
Threat-model a "redeem discount code" feature using the four questions (what are we building / what can go wrong / what do we do / did we do well). Identify at least three design-level abuse cases and the control each needs designed in.
📄 View solutionExplain the principle "you can't fix an insecure design with perfect implementation," with a worked example. Then explain why pen-testing late doesn't catch design flaws, and list four secure-by-design principles with how each would have prevented an earlier-chapter vulnerability.
📄 View solutionChapter 4 Quick Reference
- A04 Insecure Design (new in 2021) — flaws in what you build, not how it's coded; no perfect implementation can fix an insecure design
- Design vs implementation: implementation = doing the right thing wrong (fix the code); design = the right control was never specified (must be designed in)
- Looks like: missing controls (no rate limiting) · trusting client for business logic (client-sent price) · business-logic flaws (unlimited coupon, over-refund) · feature abuse · over-collection
- Threat modeling — the core practice: what are we building? · what can go wrong? (STRIDE) · what do we do? · did we do well? — done at design time
- Secure-by-design principles: least privilege · defence in depth · fail securely · secure defaults · minimize attack surface · explicit trust boundaries
- Mindset shift: security is a designed-in property, not a late testing phase — "shift left"; the cheapest security work is at the whiteboard
- Pen-testing finds implementation bugs; it rarely catches a flawed design (clean code, bad idea)
- Next chapter: A05 Security Misconfiguration — default creds, verbose errors, missing hardening