Insecure Design — OWASP Top 10 A06 (2026)

Written by the Rafter Team
· Updated

Estimated reading time: ~9 minutes
Insecure Design is OWASP Top 10 category A06 in the current 2025 edition (it was A04 back in 2021): a security control that was never built into the architecture in the first place, not a mistake in code that already exists. An implementation bug is a flaw in logic that was supposed to work — a permission check with an off-by-one error, an escaping function applied to the wrong field. Insecure design is different: the checkout flow shipped with no fraud check at all, the login page shipped with no rate limiting at all, the API was built to trust a price the client sends. No amount of clean, bug-free code fixes a control the design never specified — that takes rework at the architecture level, starting with threat modeling before the next line of code gets written.
Related: the full OWASP Top 10 2026 list · why the coding agent is the supply chain now
The Problem
You can write perfect code — and still get hacked. Why? Because the design itself is insecure.
This is the core of Insecure Design, a category in the OWASP Top 10 that focuses on security failures baked into the system's architecture from the beginning.
What It Is
Security failures baked into the system's architecture. These aren't implementation bugs — they're fundamental design flaws that make the system inherently vulnerable.
Key Characteristics
- Systemic Issues: Problems that affect the entire application design
- Not Implementation Bugs: These are architectural decisions, not coding errors
- Hard to Fix: Often require significant redesign to address properly
- Prevention Focus: Best addressed during the design phase
Examples
1. No Rate Limits on Login
Problem: Application allows unlimited login attempts Impact: Enables brute-force attacks and credential stuffing Design Fix: Implement progressive delays and account lockouts
Related: This directly leads to Authentication Failures and should be addressed in the design phase.
2. No MFA Option
Problem: Application only supports password-based authentication Impact: Vulnerable to credential stuffing and password attacks Design Fix: Build MFA support into the authentication architecture
3. Financial App with No Anti-Fraud Checks
Problem: Payment processing without fraud detection Impact: Enables fraudulent transactions Design Fix: Integrate fraud detection and transaction monitoring
Related: Without proper monitoring, this becomes a Security Logging and Monitoring Failures issue.
4. Insufficient Session Management
Problem: Sessions never expire or use weak tokens Impact: Session hijacking and unauthorized access Design Fix: Implement proper session lifecycle management
5. No Input Validation Architecture
Problem: Application lacks systematic input validation Impact: Multiple injection and XSS vulnerabilities Design Fix: Design validation framework from the start
Why It Matters
Design flaws aren't fixed with patches — they require re-architecting.
- Expensive to Fix: Requires significant development effort
- High Impact: Can affect entire application functionality
- Root Cause: Many security issues stem from poor initial design
- Compliance Issues: May violate security frameworks and standards
Real-World Impact
- Equifax (2017): Design flaw in Apache Struts led to massive data breach
- Capital One (2019): SSRF vulnerability due to insecure cloud architecture design
- SolarWinds (2020): Supply chain attack enabled by insecure software design
How to Prevent It
1. Perform Threat Modeling Early
- Identify potential threats during design phase
- Use frameworks like STRIDE or PASTA
- Document security assumptions and requirements
2. Define Security Requirements as Part of Specs
# Example security requirements
authentication:
- Must support MFA
- Must implement rate limiting
- Must use secure session management
data_protection:
- Must encrypt sensitive data at rest
- Must use TLS 1.3+ for data in transit
- Must implement proper access controls
3. Use Secure Defaults in Frameworks
- Choose frameworks with security built-in
- Enable security features by default
- Follow framework security best practices
4. Implement Security by Design Principles
- Defense in Depth: Multiple layers of security
- Fail Secure: System fails to secure state
- Least Privilege: Minimal necessary permissions
- Separation of Concerns: Isolate security functions
5. Regular Security Architecture Reviews
- Review design decisions for security implications
- Validate against security requirements
- Update threat models as system evolves
6. Security Training for Designers
- Educate architects on security principles
- Include security experts in design reviews
- Use security checklists during design phase
Tools
- OWASP Threat Dragon: Free threat modeling tool
- Microsoft SDL: Security Development Lifecycle framework
- Rafter Handbook: Security best practices guide
- STRIDE: Threat modeling methodology
- PASTA: Process for Attack Simulation and Threat Analysis
Conclusion
Security isn't just code quality — it's design quality. Insecure design creates systemic vulnerabilities that are expensive and difficult to fix later.
Next Steps:
- Conduct threat modeling for your current architecture
- Review security requirements in your design phase
- Implement secure design patterns and principles
- Include security considerations from day one of your design process
Related Resources
Frequently Asked Questions
What's an example of insecure design?
A login flow with no rate limiting or account lockout is a classic case — an attacker can try unlimited password guesses because nobody designed a limit, not because an existing check is broken. A subtler example is a payment API that trusts a price value sent by the client instead of looking it up server-side; the code runs exactly as written, but the architecture never specified that prices must be verified.
How do you fix insecure design?
Fixing insecure design means reworking the architecture, not patching a line of code. Start with threat modeling — STRIDE and PASTA are the two most common frameworks — during the design phase, and write the resulting controls into your specs as concrete requirements alongside the functional ones. Favor frameworks and defaults that make the secure path the easy path, so implementation isn't left to invent security decisions the design skipped.
Design review closes the original gap. Running a CI security check like Rafter on every pull request catches many of the coding-level symptoms in the meantime — hardcoded secrets, vulnerable dependencies, and injection flaws that tend to show up in code written against an under-specified design.
What's the difference between insecure design and security misconfiguration?
Security misconfiguration (A02) is when a control exists but is deployed incorrectly — MFA is available but the default policy doesn't enforce it, or the access-control code is correct but a storage bucket was left publicly exposed. Insecure design (A06) is when the control was never specified to begin with — there is no MFA option anywhere in the authentication architecture. One is an execution failure, and the other is a specification failure.
Why does threat modeling matter for insecure design?
Threat modeling is the design-phase practice that catches these gaps before any code gets written. Walking through how a feature could be abused — STRIDE's spoofing, tampering, repudiation, information disclosure, denial of service, and elevation of privilege — turns "we should probably think about abuse cases" into specific, testable requirements. Skip it, and security requirements only surface after an incident, when the fix costs a redesign instead of a design review.
Does insecure design show up in AI-generated code?
Yes, and increasingly so. Coding agents are good at producing logic that runs, but they inherit whatever design constraints are, or are not, in the prompt or the existing codebase, so a security requirement nobody specified doesn't get invented by the agent either. An agent asked to build a password reset flow will produce one that works, but only a design review catches whether it should rate-limit reset requests or expire tokens — the same gap that shows up in human-written code, just shipped faster.