Skip to main content

๐Ÿ›ก๏ธ Lesson 7: Security Considerations in Design Documents

Building software without security considerations is like building a house with no locks, alarms, or fences. Security isn't an afterthought โ€” it's a fundamental part of your architecture. The worst time to think about security is after a breach. The best time? Right now, in your SDD.

๐ŸŽฏ Learning Objectives

By the end of this lesson, you will be able to:

  • Apply the defense-in-depth strategy to your architecture using the castle metaphor
  • Use the STRIDE model to systematically identify threats
  • Distinguish between authentication and authorization and document both
  • Specify encryption requirements for data at rest and in transit
  • Reference the OWASP Top 10 when writing security sections of your SDD
  • Integrate security testing at every stage of the development pipeline

Estimated Time: 30 minutes

๐Ÿ“‘ In This Lesson

The Castle Defense Strategy

Medieval castles didn't rely on a single wall โ€” they used moats, outer walls, inner walls, and a fortified keep. This is defense in depth: multiple layers of security so that if one layer fails, the others still protect you. Your SDD should document each layer and what it defends against.

๐Ÿ’ก The Four Layers in Your SDD

Layer 1 โ€” Network Security (the Moat): Firewalls, VPNs, network segmentation. Keeps most attackers from even reaching your application.

Layer 2 โ€” Perimeter (the Outer Wall): WAF (Web Application Firewall), DDoS protection, rate limiting. Filters malicious traffic.

Layer 3 โ€” Application Security (the Inner Wall): Input validation, authentication, authorization, secure coding practices.

Layer 4 โ€” Data Encryption (the Keep): The last line of defense. Even if attackers breach everything else, encrypted data is useless without the keys.

The STRIDE Threat Model

STRIDE helps you think like an attacker. It's a systematic checklist: for every component in your architecture, ask "could someone Spoof, Tamper, Repudiate, disclose Information, Deny service, or Elevate privilege?" Then document the mitigation for each threat in your SDD.

graph TD S[S โ€” Spoofing] --> S1[Pretending to be someone else] T[T โ€” Tampering] --> T1[Modifying data or code] R[R โ€” Repudiation] --> R1[Denying actions performed] I[I โ€” Info Disclosure] --> I1[Exposing private data] D[D โ€” Denial of Service] --> D1[Making system unavailable] E[E โ€” Elevation of Privilege] --> E1[Gaining unauthorized access] S --> S2[Mitigation: Strong Authentication] T --> T2[Mitigation: Data Integrity Checks] R --> R2[Mitigation: Audit Logging] I --> I2[Mitigation: Encryption] D --> D2[Mitigation: Rate Limiting] E --> E2[Mitigation: Least Privilege]

โš ๏ธ Threat Modeling Isn't One-and-Done

Run STRIDE every time you add a new component, a new integration, or a new user role. A system that was secure last quarter may have new attack surfaces today. Add a "Security Review Triggers" section to your SDD that lists which changes require a threat model refresh.

Real-World Example: Banking Application Security

Banking systems are the gold standard for security architecture. Notice how this design uses network zones โ€” each zone has progressively stricter access controls, and no component in the public zone can directly reach the data zone.

Security Architecture for Online Banking

graph TB subgraph "Public Zone" U[User Browser] M[Mobile App] end subgraph "DMZ" WAF[Web Application Firewall] LB[Load Balancer] API[API Gateway] end subgraph "Application Zone" WEB[Web Servers] APP[App Servers] AUTH[Auth Service] end subgraph "Data Zone" DB[(Encrypted Database)] VAULT[Secrets Vault] LOGS[Security Logs] end U --> WAF M --> WAF WAF --> LB LB --> API API --> WEB API --> APP APP --> AUTH APP --> DB AUTH --> VAULT APP --> LOGS

๐Ÿ“– Why Zones Matter

Each zone boundary is a firewall with explicit allow-rules. The DMZ can talk to the Application Zone, but not directly to the Data Zone. The Application Zone can reach the Data Zone, but the Data Zone never initiates outbound connections. This means an attacker who compromises the API Gateway still can't reach the database without also compromising an app server. Document every zone and every allowed connection in your SDD.

Authentication vs Authorization: The Bouncer and the VIP List

These two concepts are frequently confused, but the difference is critical. Authentication (AuthN) answers "who are you?" โ€” it verifies identity. Authorization (AuthZ) answers "what are you allowed to do?" โ€” it checks permissions. You need both, and your SDD should document both separately.

๐Ÿ’ก Common Auth Patterns to Document

Authentication: JWT tokens, OAuth 2.0/OpenID Connect, SAML for enterprise SSO, API keys for service-to-service, MFA requirements (which roles? which actions?).

Authorization: RBAC (Role-Based Access Control) for most apps, ABAC (Attribute-Based) when roles aren't granular enough, resource-level permissions (can user X edit document Y?), time-limited access tokens.

๐Ÿšซ The "Admin Flag" Anti-Pattern

Don't model authorization as a single is_admin: true/false boolean. Real systems need granular permissions: who can read billing data, who can invite users, who can deploy to production. Start with RBAC and define roles like viewer, editor, billing_admin, super_admin โ€” with each role's permissions explicitly documented in the SDD.

The OWASP Top 10: Know Your Enemies

The OWASP Top 10 is the industry's most widely referenced list of web application security risks. Your SDD's security section should address how your design mitigates at least the top five:

graph LR A[OWASP Top 10] --> A1[Broken Access Control] A --> A2[Cryptographic Failures] A --> A3[Injection] A --> A4[Insecure Design] A --> A5[Security Misconfiguration] A1 --> C1[Implement RBAC] A2 --> C2[Encrypt everything] A3 --> C3[Parameterized queries] A4 --> C4[Threat modeling] A5 --> C5[Security hardening]

โš ๏ธ Injection Is Not Just SQL

When developers hear "injection," they think SQL injection. But injection attacks target any interpreter: OS commands, LDAP queries, XPath, template engines, even log files (log injection). The universal defense is: never trust user input. Validate, sanitize, and use parameterized interfaces everywhere โ€” then document your validation strategy in the SDD.

๐Ÿ“– #4 Is the One That Matters Most for SDDs

"Insecure Design" was added to the OWASP Top 10 in 2021 specifically because security can't be bolted on after the fact. A design that lacks rate limiting, doesn't separate admin and user flows, or stores secrets in config files is insecure by design. This entire lesson is about preventing #4.

Encryption: The Secret Code

Encryption is your last line of defense โ€” if everything else fails, properly encrypted data is still protected. Your SDD needs to specify encryption for two scenarios: data at rest (stored in databases, file systems, backups) and data in transit (moving between client and server, or between services).

๐Ÿ’ก What to Specify in Your SDD

At rest: AES-256 for database encryption, encrypted backups, key rotation schedule (90 days is common), key management system (AWS KMS, HashiCorp Vault, etc.).

In transit: TLS 1.3 minimum (TLS 1.2 acceptable with strong cipher suites), certificate pinning for mobile apps, mutual TLS (mTLS) for service-to-service communication.

Application-level: Bcrypt or Argon2 for password hashing (never MD5 or SHA-1), field-level encryption for PII (SSN, credit cards), envelope encryption for large datasets.

๐Ÿšซ Never Roll Your Own Crypto

This is possibly the most important rule in software security. Use battle-tested libraries (libsodium, OpenSSL, your language's standard crypto library). Even PhD cryptographers get it wrong when implementing from scratch. Document which library you use and which algorithms โ€” "we use encryption" is not a security specification.

Security Testing in Your Pipeline

Security testing shouldn't be a separate phase that happens after development. It should be woven into every stage of your CI/CD pipeline โ€” "shift left" means catching vulnerabilities as early as possible, when they're cheapest to fix.

โœ… What Each Stage Catches

SAST (Static Analysis): Scans source code for vulnerabilities before it runs โ€” catches SQL injection, hardcoded secrets, insecure patterns. Run on every commit.

Dependency Scan: Checks your package.json/requirements.txt against known vulnerability databases (CVEs). A single outdated library can be the entry point.

DAST (Dynamic Analysis): Tests the running application by sending malicious inputs โ€” finds XSS, CSRF, auth bypasses that static analysis misses.

Config Scan: Verifies deployment configurations โ€” open ports, default credentials, overly permissive IAM roles, missing security headers.

Runtime Protection: Monitors production for anomalies โ€” unusual traffic patterns, failed auth spikes, data exfiltration attempts.

Zero Trust Architecture: Trust No One

Traditional security assumes everything inside the network perimeter is trusted. Zero Trust flips this: nothing is trusted by default, whether it's inside or outside the network. Every request is verified, every connection is encrypted, every access is logged.

graph TD A[Zero Trust Principles] --> B[Verify Explicitly] A --> C[Least Privilege Access] A --> D[Assume Breach] B --> B1[Always authenticate] B --> B2[Always authorize] B --> B3[Context-aware decisions] C --> C1[Just-in-time access] C --> C2[Just-enough access] C --> C3[Time-limited permissions] D --> D1[Minimize blast radius] D --> D2[Segment everything] D --> D3[Encrypt by default]

๐Ÿ“– Zero Trust in Practice

Zero Trust doesn't mean "don't trust anyone" โ€” it means "verify before trusting." In practical terms: service-to-service calls use mTLS (not just "they're on the same network"), API tokens have short lifetimes and narrow scopes, internal dashboards require the same authentication as external ones, and every data access is logged for audit.

Security Checklist for Design Documents

๐Ÿ“ Essential Security Sections in Your SDD

Authentication & Authorization: MFA support, RBAC/ABAC model, session management, password policies, token lifetimes, service-to-service auth.

Data Protection: Encryption at rest (algorithm, key management), encryption in transit (TLS version, cipher suites), data classification levels, retention and deletion policies, backup encryption.

Application Security: Input validation strategy, output encoding (XSS prevention), parameterized queries (injection prevention), security headers (CSP, HSTS, X-Frame-Options), dependency management.

Infrastructure Security: Network segmentation and zones, firewall rules, WAF configuration, DDoS protection, secrets management (no secrets in code or config files).

Monitoring & Incident Response: Security event logging (what gets logged, where, how long), alerting thresholds, incident response playbook, breach notification plan, penetration testing schedule.

๐Ÿšซ The "Security Through Obscurity" Fallacy

Hiding your API endpoints, using non-standard ports, or obfuscating code is not security โ€” it's a speed bump that a determined attacker will bypass in minutes. Real security comes from strong authentication, proper encryption, input validation, and defense in depth. If your system's security depends on attackers not knowing how it works, it's not secure.

In the next lesson, we'll explore performance and scalability โ€” because a secure system that can't handle users is like a fortress with no food. You'll learn to document capacity requirements, caching strategies, database optimization, and scaling patterns.

๐Ÿ’ก Key Takeaway

Security is not a feature โ€” it's a quality that pervades every architectural decision. Document your threat model, your defense layers, your encryption choices, and your testing pipeline in the SDD. The goal isn't to make your system unhackable (nothing is) โ€” it's to make attacking it so expensive and slow that attackers move on to easier targets.