Building Secure and Reliable Systems
Core Insight
Security and reliability are emergent properties — impossible to retrofit. Both must be designed in from the start. They share the same root causes: complexity, hidden assumptions, and cascading failures.
Fundamental tension: Reliability favors fail-open; security requires fail-closed. Resolve this tension explicitly at design time.
Understanding Adversaries
Before designing defenses, model who you're defending against.
Attacker Profiles
| Profile |
Motivation |
Capability |
| Hobbyist |
Challenge, curiosity |
Low — opportunistic |
| Vulnerability researcher |
Recognition, bounties |
Medium — targeted |
| Activist |
Ideology, exposure |
Medium — sustained |
| Criminal actor |
Financial gain |
High — persistent |
| Nation-state / law enforcement |
Intelligence, control |
Very high — patient |
| Insider |
Grievance, profit, coercion |
Very high — trusted access |
| AI/automation |
Amplifies any of the above |
Scales attack volume |
Insiders are the hardest threat: they have legitimate access, know systems deeply, and bypass perimeter controls. Design as if insiders will turn adversarial.
Attacker Methods
- Cyber kill chains: Reconnaissance → intrusion → lateral movement → exfiltration. Disrupt any link to stop the chain.
- TTPs (Tactics, Techniques, Procedures): Attackers reuse playbooks. Threat intelligence maps known TTPs to defenses.
- Risk = Probability × Impact: Prioritize mitigations by this product, not gut feeling.
Design Principles
Least Privilege
- Grant minimum access needed; reject ambient/implicit authority
- Zero Trust: network location grants nothing — require user + device credentials
- Zero Touch: automate production access; humans interact via controlled APIs
- Use narrow, typed APIs (CRUD on IDs) instead of broad POSIX-style interfaces
- Classify access by risk (public / sensitive / highly sensitive)
- Audit with structured justification (ticket IDs, case numbers)
- Multi-Party Authorization (MPA) for sensitive actions
- Breakglass for emergencies — restrict, monitor, always investigate after use
Understandability
- Decompose into independently-reasoned components with clear boundaries
- Centralize auth, logging, rate-limiting in frameworks — not scattered across services
- Use typed interfaces (SafeHtml, TrustedSqlString) to make invalid states unrepresentable
- Minimize Trusted Computing Base (TCB) — smaller = easier to reason about
- Design invariants: properties that hold even under malicious conditions
Resilience (Defense in Depth)
- Layer independent defenses — attackers must defeat each independently
- Controlled degradation: shed less-critical features to preserve essential ones
- Blast radius control: compartmentalize by role, location, and time
- Failure domains: partition into independent copies so one event can't take all
- Maintain three tiers: primary → cached/HA fallback → minimal-dependency fallback
- Redundancy expands attack surface — design both together
Recovery
- Decouple deployment speed from policy: same system for normal rollout and emergency rollback
- Know your intended state — continuously compare deployed vs. desired, auto-repair deviations
- Avoid wall-clock time dependencies; use version/epoch or validity lists instead
- Rollbacks restore reliability but can reintroduce vulnerabilities — use deny lists + Security Version Numbers
- Test recovery paths regularly — untested emergency procedures fail when needed
Design for Change
- Architecture must support fast, safe changes — security posture decays without it
- Rate-limit as isolated microservice, not embedded logic
- Progressive rollout (canary → tested → full) applies to security changes too
DoS Mitigation
Treat DoS as a design constraint, not an ops problem.
Attacker strategy: Exhaust the cheapest resource (bandwidth, memory, threads, DB connections) relative to defender cost.
Defender strategy: Make attacks expensive for the attacker and cheap to absorb.
- Defendable architecture: Push filtering upstream (CDN, load balancer, API gateway); never let cheap requests reach expensive backends
- Graceful degradation: Shed non-critical features first; maintain core functionality under load
- Rate limiting as isolated service: Failure of rate-limiting infra shouldn't take down the protected service
- Self-inflicted attacks: Client retry storms and thundering herds are the most common real-world DoS. Require exponential backoff + jitter in all clients.
- Strategic response: Have pre-negotiated upstream filtering; know your ISP/CDN escalation path before an attack
Implementation
Writing Secure Code
| Vulnerability |
Mitigation |
| SQL Injection |
Typed APIs (TrustedSqlString) |
| XSS |
Type system + contextual escaping (SafeHtml) |
| Memory corruption |
Use memory-safe languages (Go, Java) |
| Insecure deserialization |
Protocol Buffers for untrusted input |
- Prefer frameworks over per-component implementations — fix once, protect all
- Strong static types for domain concepts (User, Width, Radius) not raw primitives
- YAGNI — don't add speculative features that expand attack surface
- Enable sanitizers (AddressSanitizer, ThreadSanitizer) in CI/CD
Deploying Securely
Threat model: benign insiders (mistakes) + malicious insiders + external attackers on insider accounts.
- Mandatory code review = multi-party authorization for code
- All build/test/deploy steps automated and locked down
- Verify what is deployed (artifact provenance), not just who triggered it
- Config-as-code: same review/test rigor as source code
- Never check secrets into version control; use dedicated secret management
- Binary provenance: document inputs, transformations, builder identity
- Route all deploys through choke points; breakglass with full audit trail
Logging and Investigation
Logs are your only source of truth during incidents. Design them as infrastructure, not afterthought.
- Immutable logs: Write to append-only storage; prevent modification even by privileged accounts
- Structured logging: Machine-parseable formats enable fast querying during crises; include request IDs for distributed tracing
- Privacy-aware: Log what happened not what was in the data — avoid logging PII, credentials, or sensitive content
- Budget explicitly: Logging has real cost; define retention tiers (hot/warm/cold) and stick to them
- Security logs to always retain: Auth events, privilege escalations, config changes, access to sensitive data
Debugging access security:
- Debugging paths are high-value attack targets — apply same access controls as production
- Require audit logging on all debug access
- Prefer read-only debugging interfaces; avoid live-attach debuggers in production
- Emergency debug access should follow breakglass patterns (restrict, monitor, investigate after use)
Testing
- Unit + integration + dynamic (fuzzing, sanitizers) + static analysis
- Test of least privilege: verify profiles have no excess permissions
- Test with least privilege: use separate credentials to prevent production impact
- Adversarial testing: simulate attacks from defined adversary perspective (reliability assumes independence; security cannot)
Incident Response
Crisis Management
- Declare early — false alarms cost less than delayed response
- Assign clear Incident Commander; avoid committee decisions under pressure
- Information sharing: reliability → broad; security → need-to-know (don't tip off adversaries)
- Keep a live incident doc; communicate status at regular intervals
- After recovery: blameless postmortem, fix root causes, update runbooks
Recovery Aftermath
After containment, recovery is its own discipline:
- Scope before acting: Enumerate all affected systems before remediating any — incomplete recovery is worse than slow recovery
- Quarantine first: Isolate compromised assets; preserve forensic state before wiping
- Credential rotation: Rotate all secrets that could have been exposed — assume broader exposure than confirmed
- System rebuilds over patching: For serious compromises, rebuild from known-good images rather than patching in place
- Recovery data integrity: Verify backups weren't themselves compromised before restoring from them
- Postmortems: Blameless, written, shared. Focus on systemic fixes not individual fault. Track action items to completion.
Disaster Planning
- Define disaster tiers with pre-agreed response strategies
- Pre-stage systems and people before incidents occur
- Tabletop exercises and game days — untested plans fail
- Emergency access: low-dependency, tested regularly, integrated into on-call
Culture
| Culture |
Practice |
| Review |
Code, config, and access changes all require peer review |
| Awareness |
Just-in-time education > passive documentation |
| Yes (managed risk) |
Measure risk; layered defenses reduce individual reviewer burden |
| Inevitability |
Blameless postmortems; study failures to build resilience |
| Sustainability |
Balance reactive work with proactive investment; prevent burnout |
Roles and responsibilities:
Security is everyone's job, but specialists amplify it — embed security engineers in teams rather than isolating in a separate org
Red teams simulate realistic attacks; blue teams detect and respond. Both are needed; red-only gives a false sense of offense advantage.
External researchers (bug bounty, academic) find what internal teams miss — build a responsible disclosure program
Certifications signal baseline knowledge but don't substitute for engineering judgment
Leadership buy-in: align security investment with business metrics
Reduce fear through canary deploys, dogfooding, progressive rollout
Job shadowing breaks silos — empathy across teams improves shared ownership
Quick Checklist
Design phase:
Implementation:
Deployment:
Operations:
1---2name: secure-reliable-systems3description: Use when designing, implementing, or reviewing systems for security and reliability — covers threat modeling, least privilege, resilience patterns, secure deployment, incident response, and security culture. Based on Google's "Building Secure and Reliable Systems".4---56# Building Secure and Reliable Systems78## Core Insight910Security and reliability are **emergent properties** — impossible to retrofit. Both must be designed in from the start. They share the same root causes: complexity, hidden assumptions, and cascading failures.1112**Fundamental tension:** Reliability favors fail-open; security requires fail-closed. Resolve this tension explicitly at design time.1314---1516## Understanding Adversaries1718Before designing defenses, model who you're defending against.1920### Attacker Profiles21| Profile | Motivation | Capability |22|---|---|---|23| Hobbyist | Challenge, curiosity | Low — opportunistic |24| Vulnerability researcher | Recognition, bounties | Medium — targeted |25| Activist | Ideology, exposure | Medium — sustained |26| Criminal actor | Financial gain | High — persistent |27| Nation-state / law enforcement | Intelligence, control | Very high — patient |28| Insider | Grievance, profit, coercion | Very high — trusted access |29| AI/automation | Amplifies any of the above | Scales attack volume |3031**Insiders are the hardest threat**: they have legitimate access, know systems deeply, and bypass perimeter controls. Design as if insiders will turn adversarial.3233### Attacker Methods34- **Cyber kill chains**: Reconnaissance → intrusion → lateral movement → exfiltration. Disrupt any link to stop the chain.35- **TTPs (Tactics, Techniques, Procedures)**: Attackers reuse playbooks. Threat intelligence maps known TTPs to defenses.36- **Risk = Probability × Impact**: Prioritize mitigations by this product, not gut feeling.3738---3940## Design Principles4142### Least Privilege43- Grant minimum access needed; reject ambient/implicit authority44- **Zero Trust**: network location grants nothing — require user + device credentials45- **Zero Touch**: automate production access; humans interact via controlled APIs46- Use narrow, typed APIs (CRUD on IDs) instead of broad POSIX-style interfaces47- Classify access by risk (public / sensitive / highly sensitive)48- Audit with structured justification (ticket IDs, case numbers)49- **Multi-Party Authorization (MPA)** for sensitive actions50- Breakglass for emergencies — restrict, monitor, always investigate after use5152### Understandability53- Decompose into independently-reasoned components with clear boundaries54- Centralize auth, logging, rate-limiting in frameworks — not scattered across services55- Use **typed interfaces** (SafeHtml, TrustedSqlString) to make invalid states unrepresentable56- Minimize Trusted Computing Base (TCB) — smaller = easier to reason about57- Design **invariants**: properties that hold even under malicious conditions5859### Resilience (Defense in Depth)60- Layer independent defenses — attackers must defeat each independently61- **Controlled degradation**: shed less-critical features to preserve essential ones62- **Blast radius control**: compartmentalize by role, location, and time63- **Failure domains**: partition into independent copies so one event can't take all64- Maintain three tiers: primary → cached/HA fallback → minimal-dependency fallback65- Redundancy expands attack surface — design both together6667### Recovery68- Decouple deployment speed from policy: same system for normal rollout and emergency rollback69- Know your **intended state** — continuously compare deployed vs. desired, auto-repair deviations70- Avoid wall-clock time dependencies; use version/epoch or validity lists instead71- Rollbacks restore reliability but can reintroduce vulnerabilities — use deny lists + Security Version Numbers72- **Test recovery paths regularly** — untested emergency procedures fail when needed7374### Design for Change75- Architecture must support fast, safe changes — security posture decays without it76- Rate-limit as isolated microservice, not embedded logic77- Progressive rollout (canary → tested → full) applies to security changes too7879### DoS Mitigation80Treat DoS as a design constraint, not an ops problem.8182**Attacker strategy**: Exhaust the cheapest resource (bandwidth, memory, threads, DB connections) relative to defender cost.8384**Defender strategy**: Make attacks expensive for the attacker and cheap to absorb.8586- **Defendable architecture**: Push filtering upstream (CDN, load balancer, API gateway); never let cheap requests reach expensive backends87- **Graceful degradation**: Shed non-critical features first; maintain core functionality under load88- **Rate limiting as isolated service**: Failure of rate-limiting infra shouldn't take down the protected service89- **Self-inflicted attacks**: Client retry storms and thundering herds are the most common real-world DoS. Require exponential backoff + jitter in all clients.90- **Strategic response**: Have pre-negotiated upstream filtering; know your ISP/CDN escalation path before an attack9192---9394## Implementation9596### Writing Secure Code97| Vulnerability | Mitigation |98|---|---|99| SQL Injection | Typed APIs (`TrustedSqlString`) |100| XSS | Type system + contextual escaping (`SafeHtml`) |101| Memory corruption | Use memory-safe languages (Go, Java) |102| Insecure deserialization | Protocol Buffers for untrusted input |103104- Prefer **frameworks** over per-component implementations — fix once, protect all105- Strong static types for domain concepts (User, Width, Radius) not raw primitives106- YAGNI — don't add speculative features that expand attack surface107- Enable sanitizers (AddressSanitizer, ThreadSanitizer) in CI/CD108109### Deploying Securely110Threat model: benign insiders (mistakes) + malicious insiders + external attackers on insider accounts.111112- **Mandatory code review** = multi-party authorization for code113- All build/test/deploy steps automated and locked down114- Verify **what** is deployed (artifact provenance), not just who triggered it115- Config-as-code: same review/test rigor as source code116- Never check secrets into version control; use dedicated secret management117- **Binary provenance**: document inputs, transformations, builder identity118- Route all deploys through choke points; breakglass with full audit trail119120### Logging and Investigation121122**Logs are your only source of truth during incidents.** Design them as infrastructure, not afterthought.123124- **Immutable logs**: Write to append-only storage; prevent modification even by privileged accounts125- **Structured logging**: Machine-parseable formats enable fast querying during crises; include request IDs for distributed tracing126- **Privacy-aware**: Log *what happened* not *what was in the data* — avoid logging PII, credentials, or sensitive content127- **Budget explicitly**: Logging has real cost; define retention tiers (hot/warm/cold) and stick to them128- **Security logs to always retain**: Auth events, privilege escalations, config changes, access to sensitive data129130**Debugging access security**:131- Debugging paths are high-value attack targets — apply same access controls as production132- Require audit logging on all debug access133- Prefer read-only debugging interfaces; avoid live-attach debuggers in production134- Emergency debug access should follow breakglass patterns (restrict, monitor, investigate after use)135136### Testing137- Unit + integration + dynamic (fuzzing, sanitizers) + static analysis138- Test *of* least privilege: verify profiles have no excess permissions139- Test *with* least privilege: use separate credentials to prevent production impact140- **Adversarial testing**: simulate attacks from defined adversary perspective (reliability assumes independence; security cannot)141142---143144## Incident Response145146### Crisis Management1471. Declare early — false alarms cost less than delayed response1482. Assign clear Incident Commander; avoid committee decisions under pressure1493. Information sharing: reliability → broad; security → need-to-know (don't tip off adversaries)1504. Keep a live incident doc; communicate status at regular intervals1515. After recovery: blameless postmortem, fix root causes, update runbooks152153### Recovery Aftermath154After containment, recovery is its own discipline:155156- **Scope before acting**: Enumerate all affected systems before remediating any — incomplete recovery is worse than slow recovery157- **Quarantine first**: Isolate compromised assets; preserve forensic state before wiping158- **Credential rotation**: Rotate all secrets that could have been exposed — assume broader exposure than confirmed159- **System rebuilds over patching**: For serious compromises, rebuild from known-good images rather than patching in place160- **Recovery data integrity**: Verify backups weren't themselves compromised before restoring from them161- **Postmortems**: Blameless, written, shared. Focus on systemic fixes not individual fault. Track action items to completion.162163### Disaster Planning164- Define disaster tiers with pre-agreed response strategies165- Pre-stage systems and people before incidents occur166- **Tabletop exercises** and game days — untested plans fail167- Emergency access: low-dependency, tested regularly, integrated into on-call168169---170171## Culture172173| Culture | Practice |174|---|---|175| Review | Code, config, and access changes all require peer review |176| Awareness | Just-in-time education > passive documentation |177| Yes (managed risk) | Measure risk; layered defenses reduce individual reviewer burden |178| Inevitability | Blameless postmortems; study failures to build resilience |179| Sustainability | Balance reactive work with proactive investment; prevent burnout |180181**Roles and responsibilities**:182- Security is everyone's job, but specialists amplify it — embed security engineers in teams rather than isolating in a separate org183- **Red teams** simulate realistic attacks; **blue teams** detect and respond. Both are needed; red-only gives a false sense of offense advantage.184- External researchers (bug bounty, academic) find what internal teams miss — build a responsible disclosure program185- Certifications signal baseline knowledge but don't substitute for engineering judgment186187- **Leadership buy-in**: align security investment with business metrics188- Reduce fear through canary deploys, dogfooding, progressive rollout189- Job shadowing breaks silos — empathy across teams improves shared ownership190191---192193## Quick Checklist194195**Design phase:**196- [ ] Least privilege on all access paths197- [ ] Failure domains and blast radius explicitly defined198- [ ] Invariants documented and testable199- [ ] Recovery path designed and tested200201**Implementation:**202- [ ] Memory-safe language or memory-safe wrappers203- [ ] Typed interfaces for security-sensitive data204- [ ] Centralized auth/logging/rate-limiting framework205- [ ] No secrets in version control206207**Deployment:**208- [ ] Mandatory code review enforced209- [ ] Artifact provenance verified210- [ ] Incremental rollout with rollback capability211- [ ] Config changes treated as code212213**Operations:**214- [ ] Runbooks tested under realistic conditions215- [ ] Emergency access provisioned and exercised216- [ ] Blameless postmortem process established217- [ ] Immutable, privacy-aware logging in place218- [ ] DoS mitigation: rate limiting upstream, client retry backoff enforced219- [ ] Threat model includes insider and automated adversaries220- [ ] Credential rotation runbook ready before incidents221- [ ] Red team / external disclosure program established