| name | threat-modeling |
| description | Threat modeling methodologies (STRIDE, DREAD), attack trees, threat modeling as code, and integration with SDLC for proactive security design |
| allowed-tools | Read, Grep, Glob, Write, Edit, Task, mcp__perplexity__*, mcp__context7__*, mcp__microsoft-learn__* |
Threat Modeling
Systematic approach to identifying, quantifying, and addressing security threats in software systems.
When to Use This Skill
Keywords: threat modeling, STRIDE, DREAD, attack trees, security design, risk assessment, threat analysis, data flow diagram, trust boundary, attack surface, threat enumeration
Use this skill when:
- Designing new systems or features
- Conducting security architecture reviews
- Identifying potential attack vectors
- Prioritizing security investments
- Documenting security assumptions
- Integrating security into SDLC
- Creating threat models as code
Quick Decision Tree
- Starting a threat model? → Begin with Threat Modeling Process
- Identifying threats? → Use STRIDE methodology
- Prioritizing threats? → Apply DREAD scoring or Attack Trees
- Automating threat models? → See references/threat-modeling-tools.md
- Specific architecture patterns? → See Architecture-Specific Threats
Threat Modeling Process
┌─────────────────────────────────────────────────────────────────┐
│ THREAT MODELING WORKFLOW │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. DECOMPOSE 2. IDENTIFY 3. PRIORITIZE │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ System │──────▶│ Threats │───────▶│ Risks │ │
│ │ Model │ │ (STRIDE) │ │ (DREAD) │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ DFD │ │ Attack │ │ Counter- │ │
│ │ Trust │ │ Trees │ │ measures │ │
│ │ Boundary │ │ Patterns │ │ Backlog │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ 4. DOCUMENT ──────▶ 5. VALIDATE ──────▶ 6. ITERATE │
│ │
└─────────────────────────────────────────────────────────────────┘
Step 1: System Decomposition
Create a Data Flow Diagram (DFD) with these elements:
| Element | Symbol | Description |
|---|---|---|
| External Entity | Rectangle | Users, external systems |
| Process | Circle | Code that transforms data |
| Data Store | Parallel lines | Databases, files, caches |
| Data Flow | Arrow | Data movement |
| Trust Boundary | Dashed line | Security perimeter |
// Example: E-commerce system decomposition
public enum ElementType
{
ExternalEntity, Process, DataStore, DataFlow
}
/// <summary>Defines a security perimeter</summary>
public sealed record TrustBoundary(
string Id,
string Name,
string Description,
IReadOnlyList<string> Elements); // IDs of contained elements
/// <summary>Data Flow Diagram element</summary>
public sealed record DfdElement
{
public required string Id { get; init; }
public required string Name { get; init; }
public required ElementType ElementType { get; init; }
public string? TrustBoundary { get; init; }
public string Description { get; init; } = "";
}
/// <summary>Connection between elements</summary>
public sealed record DataFlow
{
public required string Id { get; init; }
public required string Source { get; init; }
public required string Destination { get; init; }
public required string DataType { get; init; }
public required string Protocol { get; init; }
public bool Encrypted { get; init; }
public bool Authenticated { get; init; }
}
/// <summary>Complete system model for threat analysis</summary>
public sealed class SystemModel(string name)
{
public string Name => name;
private readonly Dictionary<string, DfdElement> _elements = new();
private readonly List<DataFlow> _flows = [];
private readonly List<TrustBoundary> _trustBoundaries = [];
public IReadOnlyDictionary<string, DfdElement> Elements => _elements;
public IReadOnlyList<DataFlow> Flows => _flows;
public IReadOnlyList<TrustBoundary> TrustBoundaries => _trustBoundaries;
public void AddElement(DfdElement element) => _elements[element.Id] = element;
public void AddFlow(DataFlow flow) => _flows.Add(flow);
public void AddTrustBoundary(TrustBoundary boundary) => _trustBoundaries.Add(boundary);
/// <summary>Identify flows that cross trust boundaries - high-risk areas</summary>
public IReadOnlyList<DataFlow> GetCrossBoundaryFlows()
{
var crossBoundary = new List<DataFlow>();
foreach (var flow in _flows)
{
var sourceBoundary = _elements[flow.Source].TrustBoundary;
var destBoundary = _elements[flow.Destination].TrustBoundary;
if (sourceBoundary != destBoundary)
crossBoundary.Add(flow);
}
return crossBoundary;
}
}
// Example usage
var model = new SystemModel("E-Commerce Platform");
// Define elements
model.AddElement(new DfdElement
{
Id = "user",
Name = "Customer",
ElementType = ElementType.ExternalEntity,
TrustBoundary = "internet",
Description = "End user accessing via browser"
});
model.AddElement(new DfdElement
{
Id = "web_app",
Name = "Web Application",
ElementType = ElementType.Process,
TrustBoundary = "dmz",
Description = "Frontend web server"
});
model.AddElement(new DfdElement
{
Id = "api",
Name = "API Gateway",
ElementType = ElementType.Process,
TrustBoundary = "internal",
Description = "Backend API services"
});
model.AddElement(new DfdElement
{
Id = "db",
Name = "Database",
ElementType = ElementType.DataStore,
TrustBoundary = "internal",
Description = "Customer and order data"
});
// Define flows
model.AddFlow(new DataFlow
{
Id = "f1",
Source = "user",
Destination = "web_app",
DataType = "HTTP Request",
Protocol = "HTTPS",
Encrypted = true,
Authenticated = false
});
// Find high-risk flows
var riskyFlows = model.GetCrossBoundaryFlows();
STRIDE Methodology
STRIDE is a threat classification framework for systematic threat identification:
| Category | Threat | Security Property | Example |
|---|---|---|---|
| Spoofing | Impersonating someone/something | Authentication | Stolen credentials, session hijacking |
| Tampering | Modifying data or code | Integrity | SQL injection, file modification |
| Repudiation | Denying actions | Non-repudiation | Missing audit logs |
| Information Disclosure | Exposing information | Confidentiality | Data breach, verbose errors |
| Denial of Service | Disrupting availability | Availability | Resource exhaustion, DDoS |
| Elevation of Privilege | Gaining unauthorized access | Authorization | Privilege escalation, IDOR |
STRIDE-per-Element Analysis
Apply STRIDE to each DFD element:
using System.Collections.Frozen;
public enum StrideCategory
{
Spoofing, Tampering, Repudiation, InformationDisclosure, DenialOfService, ElevationOfPrivilege
}
/// <summary>Which STRIDE categories apply to which element types</summary>
public static class StrideApplicability
{
public static readonly FrozenDictionary<ElementType, StrideCategory[]> Map =
new Dictionary<ElementType, StrideCategory[]>
{
[ElementType.ExternalEntity] =
[StrideCategory.Spoofing, StrideCategory.Repudiation],
[ElementType.Process] =
[StrideCategory.Spoofing, StrideCategory.Tampering, StrideCategory.Repudiation,
StrideCategory.InformationDisclosure, StrideCategory.DenialOfService,
StrideCategory.ElevationOfPrivilege],
[ElementType.DataStore] =
[StrideCategory.Tampering, StrideCategory.Repudiation,
StrideCategory.InformationDisclosure, StrideCategory.DenialOfService],
[ElementType.DataFlow] =
[StrideCategory.Tampering, StrideCategory.InformationDisclosure,
StrideCategory.DenialOfService]
}.ToFrozenDictionary();
}
/// <summary>Identified threat</summary>
public sealed record Threat
{
public required string Id { get; init; }
public required StrideCategory Category { get; init; }
public required string ElementId { get; init; }
public required string Title { get; init; }
public required string Description { get; init; }
public required string AttackVector { get; init; }
public string Impact { get; init; } = "";
public string Likelihood { get; init; } = "Medium";
public IReadOnlyList<string> Mitigations { get; init; } = [];
}
/// <summary>Threat template for generation</summary>
public sealed record ThreatTemplate(
string TitleFormat, string DescriptionFormat, string AttackVector, string[] Mitigations);
/// <summary>Systematic STRIDE threat identification</summary>
public sealed class StrideAnalyzer(SystemModel model)
{
private readonly List<Threat> _threats = [];
private int _threatCounter;
private static readonly Dictionary<(ElementType, StrideCategory), ThreatTemplate> Templates = new()
{
[(ElementType.Process, StrideCategory.Spoofing)] = new(
"Spoofing of {0}",
"Attacker impersonates {0} to gain unauthorized access",
"Credential theft, session hijacking, certificate forgery",
["Strong authentication", "Certificate pinning", "Session management"]),
[(ElementType.Process, StrideCategory.Tampering)] = new(
"Tampering with {0}",
"Attacker modifies data processed by {0}",
"Input manipulation, code injection, memory corruption",
["Input validation", "Integrity checks", "Code signing"]),
[(ElementType.DataStore, StrideCategory.InformationDisclosure)] = new(
"Information disclosure from {0}",
"Sensitive data exposed from {0}",
"SQL injection, misconfiguration, backup exposure",
["Encryption at rest", "Access controls", "Data masking"])
};
/// <summary>Perform STRIDE analysis on all elements</summary>
public IReadOnlyList<Threat> Analyze()
{
// Analyze elements
foreach (var element in model.Elements.Values)
{
if (StrideApplicability.Map.TryGetValue(element.ElementType, out var categories))
{
foreach (var category in categories)
_threats.AddRange(IdentifyThreats(element, category));
}
}
// Analyze data flows
if (StrideApplicability.Map.TryGetValue(ElementType.DataFlow, out var flowCategories))
{
foreach (var flow in model.Flows)
{
foreach (var category in flowCategories)
_threats.AddRange(IdentifyFlowThreats(flow, category));
}
}
return _threats;
}
private IEnumerable<Threat> IdentifyThreats(DfdElement element, StrideCategory category)
{
var key = (element.ElementType, category);
if (!Templates.TryGetValue(key, out var template))
yield break;
_threatCounter++;
yield return new Threat
{
Id = $"T{_threatCounter:D3}",
Category = category,
ElementId = element.Id,
Title = string.Format(template.TitleFormat, element.Name),
Description = string.Format(template.DescriptionFormat, element.Name),
AttackVector = template.AttackVector,
Mitigations = template.Mitigations
};
}
private IEnumerable<Threat> IdentifyFlowThreats(DataFlow flow, StrideCategory category)
{
if (category == StrideCategory.InformationDisclosure && !flow.Encrypted)
{
_threatCounter++;
yield return new Threat
{
Id = $"T{_threatCounter:D3}",
Category = category,
ElementId = flow.Id,
Title = $"Unencrypted data flow: {flow.Source} -> {flow.Destination}",
Description = $"Data ({flow.DataType}) transmitted without encryption",
AttackVector = "Network sniffing, man-in-the-middle",
Impact = "High - Data exposure",
Mitigations = ["Enable TLS", "Use VPN", "Encrypt at application layer"]
};
}
if (category == StrideCategory.Tampering && !flow.Authenticated)
{
_threatCounter++;
yield return new Threat
{
Id = $"T{_threatCounter:D3}",
Category = category,
ElementId = flow.Id,
Title = $"Unauthenticated data flow: {flow.Source} -> {flow.Destination}",
Description = "Data flow lacks authentication - source cannot be verified",
AttackVector = "Message injection, replay attacks",
Impact = "Medium - Data integrity compromise",
Mitigations = ["Mutual TLS", "Message signing", "API authentication"]
};
}
}
}
For detailed STRIDE analysis with examples, see references/stride-methodology.md.
DREAD Risk Scoring
DREAD provides quantitative risk assessment for prioritization:
| Factor | Description | Scale |
|---|---|---|
| Damage | Impact if exploited | 1-10 |
| Reproducibility | Ease of reproducing attack | 1-10 |
| Exploitability | Effort required to exploit | 1-10 |
| Affected Users | Scope of impact | 1-10 |
| Discoverability | Likelihood of finding vulnerability | 1-10 |
/// <summary>DREAD risk scoring</summary>
public readonly struct DreadScore
{
public int Damage { get; } // 1-10
public int Reproducibility { get; } // 1-10
public int Exploitability { get; } // 1-10
public int AffectedUsers { get; } // 1-10
public int Discoverability { get; } // 1-10
public DreadScore(int damage, int reproducibility, int exploitability,
int affectedUsers, int discoverability)
{
ValidateRange(damage, nameof(damage));
ValidateRange(reproducibility, nameof(reproducibility));
ValidateRange(exploitability, nameof(exploitability));
ValidateRange(affectedUsers, nameof(affectedUsers));
ValidateRange(discoverability, nameof(discoverability));
Damage = damage;
Reproducibility = reproducibility;
Exploitability = exploitability;
AffectedUsers = affectedUsers;
Discoverability = discoverability;
}
private static void ValidateRange(int value, string name)
{
if (value is < 1 or > 10)
throw new ArgumentOutOfRangeException(name, $"{name} must be between 1-10");
}
/// <summary>Calculate average DREAD score</summary>
public double Total => (Damage + Reproducibility + Exploitability +
AffectedUsers + Discoverability) / 5.0;
/// <summary>Categorize risk level</summary>
public string RiskLevel => Total switch
{
>= 8 => "Critical",
>= 6 => "High",
>= 4 => "Medium",
_ => "Low"
};
}
/// <summary>Prioritize threats using DREAD scoring</summary>
public sealed class ThreatPrioritizer
{
private readonly List<(Threat Threat, DreadScore Score)> _scoredThreats = [];
public void ScoreThreat(Threat threat, DreadScore score) =>
_scoredThreats.Add((threat, score));
/// <summary>Return threats sorted by risk (highest first)</summary>
public IReadOnlyList<(Threat Threat, DreadScore Score)> GetPrioritizedList() =>
_scoredThreats.OrderByDescending(x => x.Score.Total).ToList();
/// <summary>Generate risk matrix summary</summary>
public Dictionary<string, List<string>> GenerateRiskMatrix()
{
var matrix = new Dictionary<string, List<string>>
{
["Critical"] = [], ["High"] = [], ["Medium"] = [], ["Low"] = []
};
foreach (var (threat, score) in _scoredThreats)
matrix[score.RiskLevel].Add(threat.Id);
return matrix;
}
}
// Example scoring
var sqlInjectionScore = new DreadScore(
damage: 9, // Full database compromise
reproducibility: 8, // Easily reproducible with tools
exploitability: 7, // Well-known techniques
affectedUsers: 10, // All users potentially affected
discoverability: 6 // Requires testing to find
);
Console.WriteLine($"Risk Score: {sqlInjectionScore.Total}"); // 8.0
Console.WriteLine($"Risk Level: {sqlInjectionScore.RiskLevel}"); // Critical
Alternative: CVSS-Based Scoring
For compatibility with industry standards, map to CVSS:
/// <summary>CVSS 3.1 Base Score components</summary>
public sealed record CvssVector
{
public required string AttackVector { get; init; } // N, A, L, P
public required string AttackComplexity { get; init; } // L, H
public required string PrivilegesRequired { get; init; } // N, L, H
public required string UserInteraction { get; init; } // N, R
public required string Scope { get; init; } // U, C
public required string Confidentiality { get; init; } // N, L, H
public required string Integrity { get; init; } // N, L, H
public required string Availability { get; init; } // N, L, H
public string ToVectorString() =>
$"CVSS:3.1/AV:{AttackVector}/AC:{AttackComplexity}/" +
$"PR:{PrivilegesRequired}/UI:{UserInteraction}/" +
$"S:{Scope}/C:{Confidentiality}/I:{Integrity}/A:{Availability}";
}
Attack Trees
Attack trees visualize how an attacker might achieve a goal:
┌─────────────────────┐
│ Steal Customer Data │ (Goal)
└─────────────────────┘
│
┌───────────────┼───────────────┐
│ │ │
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│ SQL │ │ Phishing │ │ Insider │
│ Injection │ │ Attack │ │ Threat │
│ [OR] │ │ [OR] │ │ [OR] │
└───────────┘ └───────────┘ └───────────┘
│ │ │
┌─────┴─────┐ ┌─────┴─────┐ ┌─────┴─────┐
│ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼
┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐
│Find │ │Exploit│ │Send │ │Harvest│ │Bribe │ │Access │
│Vuln │ │Input │ │Fake │ │Creds │ │Staff │ │After │
│Endpoint│ │Field │ │Emails │ │Site │ │ │ │Hours │
│[AND] │ │[AND] │ │[AND] │ │[AND] │ │[OR] │ │[OR] │
└───────┘ └───────┘ └───────┘ └───────┘ └───────┘ └───────┘
public enum NodeOperator
{
And, // All children must succeed
Or // Any child can succeed
}
/// <summary>Node in attack tree</summary>
public sealed class AttackNode
{
public required string Id { get; init; }
public required string Description { get; init; }
public NodeOperator Operator { get; init; } = NodeOperator.Or;
public double Cost { get; init; } // Estimated attack cost
public double Probability { get; init; } = 0.5; // Success probability
public string SkillRequired { get; init; } = "Medium";
public List<AttackNode> Children { get; } = [];
public List<string> Countermeasures { get; init; } = [];
public void AddChild(AttackNode child) => Children.Add(child);
/// <summary>Calculate probability based on operator and children</summary>
public double CalculateProbability()
{
if (Children.Count == 0)
return Probability;
var childProbs = Children.Select(c => c.CalculateProbability()).ToList();
if (Operator == NodeOperator.And)
{
// All must succeed - multiply probabilities
return childProbs.Aggregate(1.0, (acc, p) => acc * p);
}
else // OR
{
// Any can succeed - 1 - (all fail)
return 1.0 - childProbs.Aggregate(1.0, (acc, p) => acc * (1 - p));
}
}
/// <summary>Calculate minimum attack cost</summary>
public double CalculateMinCost()
{
if (Children.Count == 0)
return Cost;
var childCosts = Children.Select(c => c.CalculateMinCost()).ToList();
if (Operator == NodeOperator.And)
{
// Must complete all - sum costs
return childCosts.Sum();
}
else // OR
{
// Choose cheapest path
return childCosts.Min();
}
}
}
/// <summary>Analyze attack trees for risk assessment</summary>
public sealed class AttackTreeAnalyzer(AttackNode root)
{
/// <summary>Find the least expensive attack path</summary>
public IReadOnlyList<AttackNode> FindCheapestPath() => FindPath(root, minimizeCost: true);
/// <summary>Find the most probable attack path</summary>
public IReadOnlyList<AttackNode> FindMostLikelyPath() => FindPath(root, minimizeCost: false);
private static List<AttackNode> FindPath(AttackNode node, bool minimizeCost)
{
var path = new List<AttackNode> { node };
if (node.Children.Count == 0)
return path;
if (node.Operator == NodeOperator.And)
{
// Must traverse all children
foreach (var child in node.Children)
path.AddRange(FindPath(child, minimizeCost));
}
else // OR
{
// Choose best child
var bestChild = minimizeCost
? node.Children.MinBy(c => c.CalculateMinCost())!
: node.Children.MaxBy(c => c.CalculateProbability())!;
path.AddRange(FindPath(bestChild, minimizeCost));
}
return path;
}
/// <summary>Collect all countermeasures from tree</summary>
public HashSet<string> GetAllCountermeasures() => CollectCountermeasures(root);
private static HashSet<string> CollectCountermeasures(AttackNode node)
{
var measures = new HashSet<string>(node.Countermeasures);
foreach (var child in node.Children)
measures.UnionWith(CollectCountermeasures(child));
return measures;
}
}
// Example: Build attack tree
var rootNode = new AttackNode
{
Id = "goal",
Description = "Steal Customer Data",
Operator = NodeOperator.Or
};
var sqlInjection = new AttackNode
{
Id = "sqli",
Description = "SQL Injection Attack",
Operator = NodeOperator.And,
Countermeasures = ["Parameterized queries", "WAF", "Input validation"]
};
sqlInjection.AddChild(new AttackNode
{
Id = "find_vuln",
Description = "Find vulnerable endpoint",
Cost = 100,
Probability = 0.7,
SkillRequired = "Medium"
});
sqlInjection.AddChild(new AttackNode
{
Id = "exploit",
Description = "Exploit injection point",
Cost = 200,
Probability = 0.8,
SkillRequired = "High"
});
rootNode.AddChild(sqlInjection);
// Analyze
var analyzer = new AttackTreeAnalyzer(rootNode);
Console.WriteLine($"Overall attack probability: {rootNode.CalculateProbability():P2}");
Console.WriteLine($"Minimum attack cost: ${rootNode.CalculateMinCost()}");
Console.WriteLine($"Countermeasures needed: {string.Join(", ", analyzer.GetAllCountermeasures())}");
Architecture-Specific Threats
Microservices Architecture
| Component | Key Threats | Mitigations |
|---|---|---|
| API Gateway | DDoS, injection, auth bypass | Rate limiting, WAF, OAuth |
| Service Mesh | mTLS bypass, sidecar compromise | Certificate rotation, network policies |
| Message Queue | Message tampering, replay | Message signing, idempotency |
| Service Discovery | Registry poisoning | Secure registration, health checks |
Serverless Architecture
| Component | Key Threats | Mitigations |
|---|---|---|
| Functions | Cold start attacks, injection | Input validation, minimal permissions |
| Event Sources | Event injection, DoS | Source validation, rate limiting |
| Shared Tenancy | Noisy neighbor, data leakage | Isolation, encryption |
Container/Kubernetes Architecture
| Component | Key Threats | Mitigations |
|---|---|---|
| Container Runtime | Escape, privilege escalation | Rootless, seccomp, AppArmor |
| Orchestrator | API server compromise | RBAC, audit logging, network policies |
| Registry | Image tampering, supply chain | Image signing, vulnerability scanning |
SDLC Integration
When to Threat Model
| Phase | Activity | Output |
|---|---|---|
| Design | Initial threat model | Threat register, DFD |
| Development | Update for changes | Updated threats, security tests |
| Code Review | Verify mitigations | Security checklist |
| Testing | Validate mitigations | Penetration test plan |
| Release | Final review | Risk acceptance, residual risks |
| Operations | Incident analysis | Updated threat model |
Lightweight Threat Modeling
For agile environments, use rapid threat modeling:
# threat-model.yaml - Minimal threat model per feature
feature: User Authentication
date: 2024-01-15
author: security-team
assets:
- name: User credentials
classification: Confidential
- name: Session tokens
classification: Internal
threats:
- id: AUTH-001
category: Spoofing
description: Credential stuffing attack
risk: High
mitigation: Rate limiting, MFA, breach detection
- id: AUTH-002
category: Information Disclosure
description: Token exposure in logs
risk: Medium
mitigation: Token redaction, structured logging
mitigations_implemented:
- Argon2id password hashing
- JWT with short expiration
- Refresh token rotation
open_risks:
- Legacy systems using MD5 (migration planned Q2)
Security Checklist
Before finalizing threat model:
- All trust boundaries identified
- STRIDE applied to each element
- Data flows across boundaries encrypted
- Authentication at trust boundary crossings
- Risks prioritized (DREAD/CVSS)
- Mitigations mapped to threats
- Residual risks documented
- Model reviewed by stakeholders
- Integration with issue tracking
References
- STRIDE Methodology Deep Dive - Detailed analysis with examples
- Threat Modeling Tools - pytm, threagile, automation
Version History
- v1.0.0 (2025-12-26): Initial release with STRIDE, DREAD, attack trees, architecture patterns
Last Updated: 2025-12-26