Threat Modeling
Overview
Threat modeling is the systematic identification of security threats to a system BEFORE the system is built. It answers four questions: What are we building? What can go wrong? What are we going to do about it? Did we do a good enough job? You cannot secure a system by adding security after the fact—security must be designed in. Threat modeling is how you design it in.
A threat model is not a penetration test. Penetration testing finds bugs in implementation. Threat modeling finds flaws in design. A perfectly implemented system with a flawed design is still insecure. You do threat modeling at design time; you do pen testing at implementation time. Both are required; neither replaces the other.
When to Use
- During the design phase of any new service or feature
- When adding new data flows (especially customer data or credentials)
- When changing authentication or authorization mechanisms
- When adding new external-facing endpoints (API, web, mobile)
- When integrating with a new third-party service
- When changing trust boundaries (new service-to-service communication)
- When an incident reveals a class of vulnerability (model similar systems)
- Before any Design Bar Raiser review for systems handling sensitive data
Agent Persona
Load agents/security-guardian.md when reviewing the threat model. Use it to challenge trust boundaries, data classification, least privilege, encryption, blast radius, and missing abuse cases.
Amazon Context
Threat models are living documents maintained alongside design documents. They are updated when the system changes, when new threat intelligence emerges, or when incidents reveal gaps. Every system that handles customer data, credentials, or payment information requires a formal threat model reviewed by security teams before launch.
The principle of "blast radius minimization" is paramount: design systems so that a compromise of one component cannot cascade to compromise the entire system. This drives decisions about service boundaries, IAM scope, encryption key separation, and network isolation.
The Process
1. Data Classification
Before identifying threats, classify the data your system handles:
| Classification |
Definition |
Examples |
Requirements |
| Restricted |
Compromise causes severe harm to customers or business. Regulatory implications. |
Payment card numbers, SSNs, authentication credentials, encryption keys |
Encrypted at rest AND in transit. Access logged. Minimal retention. Need-to-know access. Annual audit. |
| Confidential |
Internal business data. Competitive advantage if disclosed. |
Customer PII (name, email, address), internal financial data, unreleased product plans |
Encrypted at rest AND in transit. Access controlled by role. Retention policy enforced. |
| Internal |
Not public but low sensitivity. Operational data. |
Service metrics, internal documentation, team rosters, non-sensitive logs |
Encrypted in transit. Access controlled by team. Standard retention. |
| Public |
Intended for public consumption. |
Marketing content, public documentation, open-source code |
Integrity protection (prevent tampering). No confidentiality requirements. |
Rule: A system's classification is determined by the HIGHEST classification of data it handles. A service that processes one Restricted field is a Restricted service.
2. System Decomposition
Create a Data Flow Diagram (DFD) that identifies:
Elements
- External entities: Users, third-party services, partner systems (outside your trust boundary)
- Processes: Your services, Lambda functions, containers, batch jobs
- Data stores: Databases, caches, S3 buckets, queues, logs
- Data flows: Every arrow between elements (API calls, events, file transfers)
Trust Boundaries
Draw lines around components that share the same trust level:
┌─────────────────────── Internet (Untrusted) ───────────────────────┐
│ [Browser] [Mobile App] [Partner API] │
└──────────────────────────┬─────────────────────────────────────────┘
│ TLS
┌──────────────────────────┼─── Public Subnet ───────────────────────┐
│ [API Gateway + WAF] │
└──────────────────────────┬─────────────────────────────────────────┘
│ IAM Auth
┌──────────────────────────┼─── Private Subnet ──────────────────────┐
│ [Application Service] │
│ │ │
│ ┌────────────┼────────────┐ │
│ ▼ ▼ ▼ │
│ [DynamoDB] [S3 Bucket] [SQS Queue] │
└────────────────────────────────────────────────────────────────────┘
│ Cross-account role
┌──────────────────────────┼─── Separate Account ────────────────────┐
│ [Audit Log Store] │
└────────────────────────────────────────────────────────────────────┘
Every crossing of a trust boundary is a potential attack surface.
3. STRIDE Analysis
For each element and data flow in the DFD, systematically analyze threats using STRIDE:
| Category |
Threat |
Question to Ask |
Example |
| Spoofing |
Identity falsification |
Can an attacker pretend to be someone/something else? |
Attacker forges JWT to impersonate another user |
| Tampering |
Data modification |
Can an attacker modify data in transit or at rest? |
Man-in-the-middle modifies API request; attacker modifies S3 object |
| Repudiation |
Denying actions |
Can an actor deny performing an action with no proof? |
Admin deletes records with no audit trail |
| Information Disclosure |
Data leakage |
Can an attacker access data they shouldn't? |
Error messages expose internal system details; logs contain PII |
| Denial of Service |
Availability disruption |
Can an attacker make the system unavailable? |
Unbounded request causes OOM; regex DoS; resource exhaustion |
| Elevation of Privilege |
Unauthorized access escalation |
Can an attacker gain higher privileges? |
SSRF to access instance metadata; SQL injection to admin role |
STRIDE Per Element
For each component in your DFD, fill in:
Component: [Name]
Trust Level: [What trust boundary is it in?]
Data Classification: [Highest classification of data it touches]
| STRIDE | Applicable? | Threat Scenario | Likelihood | Impact | Mitigation |
|--------|-------------|----------------|-----------|--------|-----------|
| Spoofing | Yes/No | [Specific scenario] | H/M/L | H/M/L | [Control] |
| Tampering | Yes/No | [Specific scenario] | H/M/L | H/M/L | [Control] |
| Repudiation | Yes/No | [Specific scenario] | H/M/L | H/M/L | [Control] |
| Info Disclosure | Yes/No | [Specific scenario] | H/M/L | H/M/L | [Control] |
| DoS | Yes/No | [Specific scenario] | H/M/L | H/M/L | [Control] |
| EoP | Yes/No | [Specific scenario] | H/M/L | H/M/L | [Control] |
4. IAM Boundary Design
Principles
- Each service has its own IAM role. No shared roles between services.
- Roles are scoped to minimum needed actions and resources. Use IAM Access Analyzer.
- Cross-service access uses role assumption, not shared credentials.
- Human access to production is time-bounded and audited. No persistent admin access.
- Separate accounts for separate blast radii. Production, staging, and security tooling in different accounts.
IAM Threat Patterns
| Pattern |
Threat |
Mitigation |
| Shared IAM role across services |
Compromise of one service = compromise of all |
Separate role per service, minimum permissions |
| Wildcard resource in policy |
Any resource accessible, not just intended ones |
Explicit ARNs; use conditions for dynamic resources |
| No MFA on privileged operations |
Credential theft = full access |
Require MFA for all human privileged operations |
| Long-lived access keys |
Keys leaked in code/logs = persistent access |
Use IAM roles with temporary credentials; rotate keys <90 days |
| Instance metadata accessible |
SSRF → credential theft via 169.254.169.254 |
IMDSv2 (require token); restrict network access to metadata |
| Over-scoped Lambda execution role |
Compromised function has broad access |
Least privilege per function; separate roles per Lambda |
5. Encryption Requirements
Encryption Decision Matrix
| Data State |
Classification: Restricted |
Classification: Confidential |
Classification: Internal |
| At rest |
KMS CMK (team-managed key), key rotation enabled |
KMS CMK or AWS-managed key |
AWS-managed key or SSE-S3 |
| In transit |
TLS 1.2+ (mandatory) |
TLS 1.2+ (mandatory) |
TLS 1.2+ (recommended) |
| In memory |
Clear from memory after use; don't log |
Standard precautions |
Standard precautions |
| In backups |
Same encryption as primary |
Same encryption as primary |
AWS-managed encryption |
| In logs |
MUST NOT appear in logs |
Mask/redact; tokenize |
Acceptable in logs |
Key Management
- Key per service: Each service has its own KMS key. Compromise of one service's key doesn't expose another service's data.
- Key per data classification: Restricted and Confidential data use different keys.
- Key rotation: Automatic annual rotation enabled. Manual rotation immediately on suspected compromise.
- Key access policy: Only the owning service's role can use the key for Encrypt/Decrypt. Admin access (for rotation, deletion) is a separate role.
- Cross-account key access: Grant via key policy, not IAM policy. Explicit deny for any principal not explicitly allowed.
6. Blast Radius Analysis
Blast radius = the extent of damage if a single component is fully compromised.
Analysis Process
For each component, answer:
- If this component is fully compromised (attacker has complete control), what can they access?
- What other systems trust this component? (follow the trust relationships)
- What data can be exfiltrated? (follow the data flows)
- Can the attacker move laterally? (check network access, shared credentials, role chaining)
- What's the recovery time? (how long to detect, contain, and recover)
Blast Radius Containment Strategies
| Strategy |
Implementation |
Reduces Blast Radius By |
| Service isolation |
Separate IAM roles per service |
Prevents lateral movement via credentials |
| Network segmentation |
Security groups with explicit allow lists |
Prevents network-based lateral movement |
| Account boundaries |
Separate AWS accounts for different trust levels |
Hard boundary; cross-account requires explicit grant |
| Data compartmentalization |
Different encryption keys per data domain |
Compromised key exposes only one domain |
| Privilege separation |
Read and write through different roles/paths |
Compromised read path can't modify data |
| Secret rotation |
Automated, frequent rotation of all secrets |
Limits window of exposure for leaked secrets |
| Circuit breakers |
Rate limits between services |
Prevents cascading resource exhaustion |
Blast Radius Scoring
Rate each component:
| Score |
Blast Radius |
Criteria |
| Critical |
System-wide compromise |
Component has admin access, cross-service credentials, or access to encryption keys for multiple services |
| High |
Multiple services affected |
Component can access data or systems beyond its own boundary |
| Medium |
Single service affected |
Compromise is contained to this service's data and functionality |
| Low |
Minimal impact |
Component is stateless, has no persistent data access, and is easily replaced |
Any component scoring "Critical" must be re-architected to reduce blast radius.
7. Common Attack Patterns (Cloud-Specific)
| Attack |
Vector |
Mitigation |
| SSRF to metadata |
Application fetches attacker-controlled URL → 169.254.169.254 |
IMDSv2; block metadata IP in application egress |
| Confused deputy |
Attacker tricks your service into acting on their behalf |
External ID in cross-account roles; validate caller identity |
| S3 bucket enumeration |
Predictable bucket names → unauthorized access |
Random bucket name suffixes; block public access; bucket policies |
| Lambda event injection |
Malicious input in event payload |
Validate and sanitize all event fields; treat events as untrusted |
| IAM privilege escalation |
iam:PassRole + lambda:CreateFunction = arbitrary code execution as any role |
Restrict iam:PassRole to specific role ARNs; permissions boundaries |
| Supply chain attack |
Compromised dependency in build pipeline |
Pin dependencies; verify checksums; scan for vulnerabilities; use private registry |
| Log injection |
Attacker injects malicious content into logs → exploits log viewers |
Sanitize log output; structured logging; separate log viewers from production |
Mechanisms Over Good Intentions
| Intention |
Mechanism |
| "I'll encrypt sensitive data" |
KMS key policies that deny unencrypted writes; S3 bucket policies that require SSE |
| "I'll follow least privilege" |
IAM Access Analyzer reviews weekly; over-permissioned roles auto-generate tickets |
| "I'll audit access to sensitive data" |
CloudTrail data events mandatory for all Restricted/Confidential data stores |
| "I'll keep secrets safe" |
Secrets Manager with automated rotation; credential scanning in CI blocks commits with secrets |
| "I'll limit blast radius" |
Separate AWS accounts per trust boundary; network isolation verified by automated tests |
Common Rationalizations
| What They Say |
Why It's Wrong |
What To Do Instead |
| "We'll add security later, we need to ship fast" |
Security bolted on after the fact is expensive and incomplete. Architecture decisions made without threat modeling create vulnerabilities that require re-architecture to fix. |
Threat model during design. It takes 2-4 hours. Re-architecting for security later takes weeks. |
| "We're not a target; attackers focus on bigger companies" |
Automated attacks don't discriminate. Bots scan every public endpoint. Supply chain attacks target small components. You ARE a target the moment you have a public endpoint or store customer data. |
Model threats regardless of perceived risk. The model will tell you which threats are low-likelihood. Don't skip the analysis. |
| "Our data isn't that sensitive" |
Have you classified it? PII includes name + email. Payment data includes partial card numbers. Internal data includes access patterns that reveal business strategy. |
Classify your data formally. You may be surprised what's actually Confidential when you apply the classification framework. |
| "IAM is too complex; we'll use broad permissions and tighten later" |
Tightening permissions breaks things. Teams never tighten. Broad permissions persist forever and become the assumed blast radius. |
Start with zero permissions. Add one permission at a time. Use IAM Access Analyzer to verify you're not over-provisioned. |
| "Encryption at rest doesn't matter if the network is secure" |
Networks are breached. Insiders exist. Backups are stolen. Disks are improperly decommissioned. Encryption at rest is defense in depth, not redundancy. |
Encrypt at rest. Always. The cost is negligible. The protection is essential. |
Red Flags
- No threat model exists for a service handling customer data
- Threat model was written once and never updated (system has changed significantly since)
- STRIDE analysis is superficial ("Spoofing: N/A" for an authentication system)
- IAM policies use
Resource: "*" with no documented justification
- Same encryption key used across multiple services
- No data classification has been performed; team can't articulate what classification their data falls under
- Blast radius analysis shows a single component compromise = system-wide breach
- Secrets (API keys, passwords, tokens) found in code repositories, config files, or logs
- No audit logging for access to Restricted or Confidential data
- Trust boundaries aren't defined; all services communicate freely without authentication
- No automated credential scanning in the CI pipeline
- IMDSv1 is enabled (allows SSRF-based credential theft)
Verification
Tenets
- Security is designed in, not bolted on. Threat modeling happens at design time. If you're threat modeling after launch, you're patching, not designing.
- Blast radius above all. The most important security property is containment. A compromised component must not cascade. Design for breach, not just prevention.
- Data classification drives everything. Encryption, access control, logging, retention—all determined by data classification. Classify first, then secure.
- Assume breach. Design every component as if the adjacent component is already compromised. This drives proper authentication, authorization, and isolation between every boundary.
- Least privilege is the default. Zero permissions until explicitly granted. Every grant is documented, justified, scoped, and auditable.
1---2name: threat-modeling3description: Security threat modeling using STRIDE methodology adapted for cloud services. Covers data classification, IAM boundaries, encryption requirements, blast radius analysis, and systematic identification of attack vectors before code is written.4---56# Threat Modeling78## Overview910Threat modeling is the systematic identification of security threats to a system BEFORE the system is built. It answers four questions: What are we building? What can go wrong? What are we going to do about it? Did we do a good enough job? You cannot secure a system by adding security after the fact—security must be designed in. Threat modeling is how you design it in.1112A threat model is not a penetration test. Penetration testing finds bugs in implementation. Threat modeling finds flaws in design. A perfectly implemented system with a flawed design is still insecure. You do threat modeling at design time; you do pen testing at implementation time. Both are required; neither replaces the other.1314## When to Use1516- During the design phase of any new service or feature17- When adding new data flows (especially customer data or credentials)18- When changing authentication or authorization mechanisms19- When adding new external-facing endpoints (API, web, mobile)20- When integrating with a new third-party service21- When changing trust boundaries (new service-to-service communication)22- When an incident reveals a class of vulnerability (model similar systems)23- Before any Design Bar Raiser review for systems handling sensitive data2425## Agent Persona2627Load `agents/security-guardian.md` when reviewing the threat model. Use it to challenge trust boundaries, data classification, least privilege, encryption, blast radius, and missing abuse cases.2829## Amazon Context3031Threat models are living documents maintained alongside design documents. They are updated when the system changes, when new threat intelligence emerges, or when incidents reveal gaps. Every system that handles customer data, credentials, or payment information requires a formal threat model reviewed by security teams before launch.3233The principle of "blast radius minimization" is paramount: design systems so that a compromise of one component cannot cascade to compromise the entire system. This drives decisions about service boundaries, IAM scope, encryption key separation, and network isolation.3435## The Process3637### 1. Data Classification3839Before identifying threats, classify the data your system handles:4041| Classification | Definition | Examples | Requirements |42|---------------|-----------|----------|-------------|43| **Restricted** | Compromise causes severe harm to customers or business. Regulatory implications. | Payment card numbers, SSNs, authentication credentials, encryption keys | Encrypted at rest AND in transit. Access logged. Minimal retention. Need-to-know access. Annual audit. |44| **Confidential** | Internal business data. Competitive advantage if disclosed. | Customer PII (name, email, address), internal financial data, unreleased product plans | Encrypted at rest AND in transit. Access controlled by role. Retention policy enforced. |45| **Internal** | Not public but low sensitivity. Operational data. | Service metrics, internal documentation, team rosters, non-sensitive logs | Encrypted in transit. Access controlled by team. Standard retention. |46| **Public** | Intended for public consumption. | Marketing content, public documentation, open-source code | Integrity protection (prevent tampering). No confidentiality requirements. |4748**Rule**: A system's classification is determined by the HIGHEST classification of data it handles. A service that processes one Restricted field is a Restricted service.4950### 2. System Decomposition5152Create a Data Flow Diagram (DFD) that identifies:5354#### Elements5556- **External entities**: Users, third-party services, partner systems (outside your trust boundary)57- **Processes**: Your services, Lambda functions, containers, batch jobs58- **Data stores**: Databases, caches, S3 buckets, queues, logs59- **Data flows**: Every arrow between elements (API calls, events, file transfers)6061#### Trust Boundaries6263Draw lines around components that share the same trust level:6465```66┌─────────────────────── Internet (Untrusted) ───────────────────────┐67│ [Browser] [Mobile App] [Partner API] │68└──────────────────────────┬─────────────────────────────────────────┘69 │ TLS70┌──────────────────────────┼─── Public Subnet ───────────────────────┐71│ [API Gateway + WAF] │72└──────────────────────────┬─────────────────────────────────────────┘73 │ IAM Auth74┌──────────────────────────┼─── Private Subnet ──────────────────────┐75│ [Application Service] │76│ │ │77│ ┌────────────┼────────────┐ │78│ ▼ ▼ ▼ │79│ [DynamoDB] [S3 Bucket] [SQS Queue] │80└────────────────────────────────────────────────────────────────────┘81 │ Cross-account role82┌──────────────────────────┼─── Separate Account ────────────────────┐83│ [Audit Log Store] │84└────────────────────────────────────────────────────────────────────┘85```8687Every crossing of a trust boundary is a potential attack surface.8889### 3. STRIDE Analysis9091For each element and data flow in the DFD, systematically analyze threats using STRIDE:9293| Category | Threat | Question to Ask | Example |94|----------|--------|----------------|---------|95| **S**poofing | Identity falsification | Can an attacker pretend to be someone/something else? | Attacker forges JWT to impersonate another user |96| **T**ampering | Data modification | Can an attacker modify data in transit or at rest? | Man-in-the-middle modifies API request; attacker modifies S3 object |97| **R**epudiation | Denying actions | Can an actor deny performing an action with no proof? | Admin deletes records with no audit trail |98| **I**nformation Disclosure | Data leakage | Can an attacker access data they shouldn't? | Error messages expose internal system details; logs contain PII |99| **D**enial of Service | Availability disruption | Can an attacker make the system unavailable? | Unbounded request causes OOM; regex DoS; resource exhaustion |100| **E**levation of Privilege | Unauthorized access escalation | Can an attacker gain higher privileges? | SSRF to access instance metadata; SQL injection to admin role |101102#### STRIDE Per Element103104For each component in your DFD, fill in:105106```107Component: [Name]108Trust Level: [What trust boundary is it in?]109Data Classification: [Highest classification of data it touches]110111| STRIDE | Applicable? | Threat Scenario | Likelihood | Impact | Mitigation |112|--------|-------------|----------------|-----------|--------|-----------|113| Spoofing | Yes/No | [Specific scenario] | H/M/L | H/M/L | [Control] |114| Tampering | Yes/No | [Specific scenario] | H/M/L | H/M/L | [Control] |115| Repudiation | Yes/No | [Specific scenario] | H/M/L | H/M/L | [Control] |116| Info Disclosure | Yes/No | [Specific scenario] | H/M/L | H/M/L | [Control] |117| DoS | Yes/No | [Specific scenario] | H/M/L | H/M/L | [Control] |118| EoP | Yes/No | [Specific scenario] | H/M/L | H/M/L | [Control] |119```120121### 4. IAM Boundary Design122123#### Principles1241251. **Each service has its own IAM role.** No shared roles between services.1262. **Roles are scoped to minimum needed actions and resources.** Use IAM Access Analyzer.1273. **Cross-service access uses role assumption**, not shared credentials.1284. **Human access to production is time-bounded and audited.** No persistent admin access.1295. **Separate accounts for separate blast radii.** Production, staging, and security tooling in different accounts.130131#### IAM Threat Patterns132133| Pattern | Threat | Mitigation |134|---------|--------|-----------|135| Shared IAM role across services | Compromise of one service = compromise of all | Separate role per service, minimum permissions |136| Wildcard resource in policy | Any resource accessible, not just intended ones | Explicit ARNs; use conditions for dynamic resources |137| No MFA on privileged operations | Credential theft = full access | Require MFA for all human privileged operations |138| Long-lived access keys | Keys leaked in code/logs = persistent access | Use IAM roles with temporary credentials; rotate keys <90 days |139| Instance metadata accessible | SSRF → credential theft via 169.254.169.254 | IMDSv2 (require token); restrict network access to metadata |140| Over-scoped Lambda execution role | Compromised function has broad access | Least privilege per function; separate roles per Lambda |141142### 5. Encryption Requirements143144#### Encryption Decision Matrix145146| Data State | Classification: Restricted | Classification: Confidential | Classification: Internal |147|-----------|---------------------------|-----------------------------|-----------------------|148| At rest | KMS CMK (team-managed key), key rotation enabled | KMS CMK or AWS-managed key | AWS-managed key or SSE-S3 |149| In transit | TLS 1.2+ (mandatory) | TLS 1.2+ (mandatory) | TLS 1.2+ (recommended) |150| In memory | Clear from memory after use; don't log | Standard precautions | Standard precautions |151| In backups | Same encryption as primary | Same encryption as primary | AWS-managed encryption |152| In logs | MUST NOT appear in logs | Mask/redact; tokenize | Acceptable in logs |153154#### Key Management155156- **Key per service**: Each service has its own KMS key. Compromise of one service's key doesn't expose another service's data.157- **Key per data classification**: Restricted and Confidential data use different keys.158- **Key rotation**: Automatic annual rotation enabled. Manual rotation immediately on suspected compromise.159- **Key access policy**: Only the owning service's role can use the key for Encrypt/Decrypt. Admin access (for rotation, deletion) is a separate role.160- **Cross-account key access**: Grant via key policy, not IAM policy. Explicit deny for any principal not explicitly allowed.161162### 6. Blast Radius Analysis163164Blast radius = the extent of damage if a single component is fully compromised.165166#### Analysis Process167168For each component, answer:1691. **If this component is fully compromised (attacker has complete control), what can they access?**1702. **What other systems trust this component?** (follow the trust relationships)1713. **What data can be exfiltrated?** (follow the data flows)1724. **Can the attacker move laterally?** (check network access, shared credentials, role chaining)1735. **What's the recovery time?** (how long to detect, contain, and recover)174175#### Blast Radius Containment Strategies176177| Strategy | Implementation | Reduces Blast Radius By |178|----------|---------------|------------------------|179| Service isolation | Separate IAM roles per service | Prevents lateral movement via credentials |180| Network segmentation | Security groups with explicit allow lists | Prevents network-based lateral movement |181| Account boundaries | Separate AWS accounts for different trust levels | Hard boundary; cross-account requires explicit grant |182| Data compartmentalization | Different encryption keys per data domain | Compromised key exposes only one domain |183| Privilege separation | Read and write through different roles/paths | Compromised read path can't modify data |184| Secret rotation | Automated, frequent rotation of all secrets | Limits window of exposure for leaked secrets |185| Circuit breakers | Rate limits between services | Prevents cascading resource exhaustion |186187#### Blast Radius Scoring188189Rate each component:190191| Score | Blast Radius | Criteria |192|-------|-------------|----------|193| Critical | System-wide compromise | Component has admin access, cross-service credentials, or access to encryption keys for multiple services |194| High | Multiple services affected | Component can access data or systems beyond its own boundary |195| Medium | Single service affected | Compromise is contained to this service's data and functionality |196| Low | Minimal impact | Component is stateless, has no persistent data access, and is easily replaced |197198Any component scoring "Critical" must be re-architected to reduce blast radius.199200### 7. Common Attack Patterns (Cloud-Specific)201202| Attack | Vector | Mitigation |203|--------|--------|-----------|204| SSRF to metadata | Application fetches attacker-controlled URL → 169.254.169.254 | IMDSv2; block metadata IP in application egress |205| Confused deputy | Attacker tricks your service into acting on their behalf | External ID in cross-account roles; validate caller identity |206| S3 bucket enumeration | Predictable bucket names → unauthorized access | Random bucket name suffixes; block public access; bucket policies |207| Lambda event injection | Malicious input in event payload | Validate and sanitize all event fields; treat events as untrusted |208| IAM privilege escalation | iam:PassRole + lambda:CreateFunction = arbitrary code execution as any role | Restrict iam:PassRole to specific role ARNs; permissions boundaries |209| Supply chain attack | Compromised dependency in build pipeline | Pin dependencies; verify checksums; scan for vulnerabilities; use private registry |210| Log injection | Attacker injects malicious content into logs → exploits log viewers | Sanitize log output; structured logging; separate log viewers from production |211212## Mechanisms Over Good Intentions213214| Intention | Mechanism |215|-----------|-----------|216| "I'll encrypt sensitive data" | KMS key policies that deny unencrypted writes; S3 bucket policies that require SSE |217| "I'll follow least privilege" | IAM Access Analyzer reviews weekly; over-permissioned roles auto-generate tickets |218| "I'll audit access to sensitive data" | CloudTrail data events mandatory for all Restricted/Confidential data stores |219| "I'll keep secrets safe" | Secrets Manager with automated rotation; credential scanning in CI blocks commits with secrets |220| "I'll limit blast radius" | Separate AWS accounts per trust boundary; network isolation verified by automated tests |221222## Common Rationalizations223224| What They Say | Why It's Wrong | What To Do Instead |225|---------------|---------------|-------------------|226| "We'll add security later, we need to ship fast" | Security bolted on after the fact is expensive and incomplete. Architecture decisions made without threat modeling create vulnerabilities that require re-architecture to fix. | Threat model during design. It takes 2-4 hours. Re-architecting for security later takes weeks. |227| "We're not a target; attackers focus on bigger companies" | Automated attacks don't discriminate. Bots scan every public endpoint. Supply chain attacks target small components. You ARE a target the moment you have a public endpoint or store customer data. | Model threats regardless of perceived risk. The model will tell you which threats are low-likelihood. Don't skip the analysis. |228| "Our data isn't that sensitive" | Have you classified it? PII includes name + email. Payment data includes partial card numbers. Internal data includes access patterns that reveal business strategy. | Classify your data formally. You may be surprised what's actually Confidential when you apply the classification framework. |229| "IAM is too complex; we'll use broad permissions and tighten later" | Tightening permissions breaks things. Teams never tighten. Broad permissions persist forever and become the assumed blast radius. | Start with zero permissions. Add one permission at a time. Use IAM Access Analyzer to verify you're not over-provisioned. |230| "Encryption at rest doesn't matter if the network is secure" | Networks are breached. Insiders exist. Backups are stolen. Disks are improperly decommissioned. Encryption at rest is defense in depth, not redundancy. | Encrypt at rest. Always. The cost is negligible. The protection is essential. |231232## Red Flags233234- No threat model exists for a service handling customer data235- Threat model was written once and never updated (system has changed significantly since)236- STRIDE analysis is superficial ("Spoofing: N/A" for an authentication system)237- IAM policies use `Resource: "*"` with no documented justification238- Same encryption key used across multiple services239- No data classification has been performed; team can't articulate what classification their data falls under240- Blast radius analysis shows a single component compromise = system-wide breach241- Secrets (API keys, passwords, tokens) found in code repositories, config files, or logs242- No audit logging for access to Restricted or Confidential data243- Trust boundaries aren't defined; all services communicate freely without authentication244- No automated credential scanning in the CI pipeline245- IMDSv1 is enabled (allows SSRF-based credential theft)246247## Verification248249- [ ] Data classification is documented for all data the system handles250- [ ] Data Flow Diagram exists showing all components, data stores, and trust boundaries251- [ ] STRIDE analysis completed for every component crossing a trust boundary252- [ ] IAM roles follow least privilege (verified by IAM Access Analyzer)253- [ ] Encryption requirements match data classification (see matrix above)254- [ ] Blast radius analysis completed; no "Critical" components exist without documented mitigation plan255- [ ] Secrets are stored in Secrets Manager/Parameter Store, never in code or config files256- [ ] Automated credential scanning runs in CI pipeline257- [ ] Audit logging enabled for all access to Restricted/Confidential data258- [ ] IMDSv2 enforced on all EC2 instances259- [ ] Network segmentation verified (security groups have explicit allow lists, not 0.0.0.0/0)260- [ ] Threat model reviewed by AppSec for any system handling Restricted data261- [ ] Threat model update schedule defined (at minimum: every major feature addition)262263## Tenets2642651. **Security is designed in, not bolted on.** Threat modeling happens at design time. If you're threat modeling after launch, you're patching, not designing.2662. **Blast radius above all.** The most important security property is containment. A compromised component must not cascade. Design for breach, not just prevention.2673. **Data classification drives everything.** Encryption, access control, logging, retention—all determined by data classification. Classify first, then secure.2684. **Assume breach.** Design every component as if the adjacent component is already compromised. This drives proper authentication, authorization, and isolation between every boundary.2695. **Least privilege is the default.** Zero permissions until explicitly granted. Every grant is documented, justified, scoped, and auditable.