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 flawDesign flaw (A04)
What's wrongthe code does the right thing wrongthe right thing to do was never specified
Examplea query that should be parameterized isn'tno rate limit was ever designed for password reset
Fixable in code?yes — fix the lineno — the missing control must be designed in
"You cannot fix an insecure design with perfect implementation"
This is the line to remember. If a feature is designed without a needed security control, then flawlessly implementing that design just gives you a flawlessly-built insecure feature. Example: a "recover account via security questions" flow. You can implement it with perfect code — parameterized queries, no XSS, great error handling — and it's still insecure, because security questions are a weak design (answers are public/guessable, Auth course). The vulnerability isn't a bug; it's the choice of mechanism. A04 says: security has to start at design time, not be bolted on after the code is written.

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.
// A design flaw, not a code bug: trusting the client for the price // POST /checkout { "item": "laptop", "price": 1299 } ← price from the browser total = req.body.price * qty; // attacker sends price: 1 → buys a laptop for $1 // No line of code is "wrong" — the DESIGN trusts client-supplied business data. // Correct design: the SERVER looks up the price from the catalogue by item id.

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):

  1. What are we building? — a clear picture of the feature, its data, and its trust boundaries (where data crosses from untrusted to trusted).
  2. What can go wrong? — brainstorm threats (a useful mnemonic is STRIDE: Spoofing, Tampering, Repudiation, Information disclosure, Denial of service, Elevation of privilege).
  3. What are we going to do about it? — decide which controls to design in (rate limits, server-side validation, authorization checks, abuse caps).
  4. 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.
Security as a phase vs security as a property
The deeper message of A04 is a mindset shift: security is not a testing phase bolted on at the end ("we'll pen-test before launch"), it's a property designed in from the start. Pen-testing and code review find implementation bugs, but they rarely catch a fundamentally insecure design — a reviewer sees clean code implementing a flawed idea. The expensive lesson many teams learn is that the cheapest security work happens at the whiteboard: think about abuse cases and threats before building, write security requirements alongside functional ones, and use reference architectures/secure patterns. "Shift left" is the industry phrase; A04 is its Top 10 home.

Hands-On Exercises

Exercise 1

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.

📄 View solution
Exercise 2

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 solution
Exercise 3

Explain 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 solution

Chapter 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