A threat model does not become correct because the diagram is attractive.
It becomes useful when it reflects the system people actually operate, shows how threats can cross real trust boundaries, connects those paths to consequences and controls, and changes as the system changes. I cover this process in detail in Cybersecurity Architect’s Handbook, Second Edition, including the downloadable supplemental material for Chapter 9.
My lab threat model had to move several times in a short period. Network zones changed. A new security plane became authoritative. Legacy platforms moved from active to stopped, then to retained backup. A secrets service moved to a dedicated system. New identity, backup, DevSecOps, remote-access, and control-plane components introduced dependencies that were not present in the earlier model. Recovery canaries added copies of sensitive systems that were intentionally isolated but still relevant to risk.
Adding a note to the old diagram would not have been enough.
The architecture had changed. The trust boundaries, concentration risks, administration paths, and recovery assumptions had changed with it. The model needed a new evidence date, updated diagrams, new attack paths, rescored risks, and an explicit statement about what remained unverified.
This closes the sequence that started with safe rollout automation, continued through coverage and retirement, and tested recovery. Those activities only improve architecture when their results feed back into the risk model.
Model state, not intent
Design documents describe intended architecture. Threat models need both intended and observed state.

A service may be:
- designed but not deployed
- deployed but not accepted
- accepted and authoritative
- active only for a migration comparison
- restricted under a hold
- stopped but recoverable
- retired with retained data
- restored into an isolated canary
- missing a required dependency
Those states create different attack paths.
A planned identity provider that protects no applications does not reduce current authentication risk. A stopped legacy SIEM with valid credentials and an easy production restore path still affects recovery and exposure. A backup server without an accepted restore does not satisfy the same control claim as one with current recovery evidence. A firewall policy committed to source but not read back from the gateway is intended state, not enforced state.
I use an implementation-state vocabulary in the model:
component_state:
value: accepted
allowed_values:
- planned
- staged
- restricted
- accepted
- degraded
- retired
- recovery-only
observed_at: 2026-09-06T20:00:00Z
evidence:
- configuration-readback
- positive-connectivity-test
- negative-connectivity-test
authority: productionThe vocabulary is not important by itself. The key is refusing to describe a planned control as if it already changes the attack path.
Build the evidence inventory first

Before drawing, I list the evidence that can change the model:
- current infrastructure inventory and power state
- physical host and storage placement
- network zones, subnets, routes, NAT, firewall policy, and same-segment paths
- DNS, load balancer, and service-discovery records
- identity providers, trust relationships, groups, service identities, and break-glass paths
- secrets platforms, PKI, key custody, and recovery material
- application data flows and external dependencies
- administrative paths and automation identities
- logging, detection, alerting, and response paths
- backups, retention, restore networks, and recovery tests
- accepted changes, open gates, exceptions, and retired systems
- prior threat model and risk register
Each source gets a collection time and authority:
sources:
- id: S1
type: network-controller-readback
collected_at: 2026-09-06T19:20:00Z
authority: enforced-network-policy
scope: zones-routes-firewall
- id: S2
type: version-controlled-service-inventory
revision: 4f6c2a1
collected_at: 2026-09-06T19:25:00Z
authority: intended-service-state
scope: owners-endpoints-lifecycle
- id: S3
type: isolated-restore-acceptance
collected_at: 2026-09-02T11:40:00Z
authority: recovery-evidence
scope: one-selected-workloadThis prevents a common mistake: combining a live firewall export, a six-month-old CMDB, and a proposed architecture slide without distinguishing their authority.
When sources conflict, the conflict is a finding. Do not quietly select the value that makes the diagram cleaner.
Separate physical and logical views
One diagram rarely explains both failure domains and attack paths well.

I keep a physical view for:
- sites, rooms, racks, and physical hosts where relevant
- hypervisor placement
- storage systems and data paths
- network devices and uplinks
- power or hardware concentration
- backup location
- high-availability and replication placement
- dependencies that share one failure domain
I keep a logical view for:
- trust zones
- identities and authentication flows
- application and data flows
- administration paths
- policy-enforcement points
- logging and response paths
- external services
- secrets and key flows
- recovery and restore boundaries
The physical view can reveal that three logical cluster members sit on one hypervisor or one power source. The logical view can reveal that a low-trust workload reaches a management API through a path hidden by physical layout.
Trying to show everything on one sheet usually produces unreadable arrows and encourages reviewers to stop asking what each line means.
The diagrams should use stable component and flow IDs that link to the written model:
C-014 Enterprise log platform
C-027 Backup repository
TB-006 Management boundary
DF-031 Endpoint telemetry to log edge
AP-009 Automation controller to hypervisor API
RP-004 Isolated restore data pathAn arrow without protocol, direction, data class, and authority is decoration.
Administration paths need their own model
Application traffic gets most of the attention. Administrative access usually has more authority.

I model:
- operator workstation to management plane
- automation agent to APIs and SSH
- CI runner to deployment worker
- deployment worker to target
- identity administrator to directory or IdP
- secrets operator to recovery material
- hypervisor administrator to guest console
- backup administrator to restore capability
- out-of-band management to physical hosts
For each path, record source identity, destination, protocol, authentication, authorization scope, network enforcement, audit destination, and recovery behavior.
administration_path:
id: AP-009
source: automation-controller
destination: virtualization-api
transport: https
authentication: api-token
authorization: guest-audit-and-bounded-backup
network_policy: exact-source-to-management-endpoint
audit: platform-audit-log-to-siem
prohibited_actions:
- host-reboot
- network-reconfiguration
- unrestricted-consoleA general arrow labelled "management" hides the part of the model an attacker wants most.
Recovery is a trust boundary
Backup diagrams often show one arrow from production to storage. That misses recovery authority.

A backup system can reconstruct a domain controller, secrets platform, CI control plane, SIEM, or application database. Whoever can restore and start that copy may gain the authority contained inside it. Recovery keys, hypervisor privileges, storage access, and network placement therefore form a control plane of their own.
The model should include:
- backup producer identity
- repository write and delete permissions
- retention and immutability controls
- encryption and key custody
- verification jobs
- restore operator authority
- restore target storage
- recovery network
- cloned identity controls
- evidence and cleanup paths
An isolated restore can reduce uncertainty and create a temporary risk at the same time. The canary contains sensitive state. It needs lifecycle, ownership, isolation, and destruction criteria.
I mark recovery-only components explicitly. They are not production services, but they are not absent.
Turn flows into attack paths
A data-flow diagram is an input to threat modeling, not the final result.

For each important flow or administration path, ask:
- What threat source can reach or influence it?
- What event could occur?
- Which condition makes the event plausible?
- Which boundary would be crossed?
- What asset or mission would be affected?
- Which preventive, detective, and recovery controls apply?
- What evidence shows those controls exist and operate?
- What uncertainty remains?
A concise path record might be:
attack_path:
id: TM-017
title: Compromised build job reaches deployment authority
threat_source: malicious-contributor-or-compromised-dependency
entry: untrusted-build-runner
path:
- execute-contributor-controlled-code
- obtain-or-reach-deployment-credential
- submit-artifact-or-command-to-production
predisposing_conditions:
- shared-runner-and-deployer-identity
- unrestricted-runner-egress
- mutable-artifact-reference
impact:
confidentiality: high
integrity: high
availability: high
controls:
preventive:
- separate-build-and-deployment-identities
- immutable-digest-promotion
- exact-network-policy
detective:
- deployment-receipt-validation
- ci-and-platform-audit-correlation
recovery:
- retained-prior-release
- credential-revocation-runbookThis is more useful than listing every threat technique that might be associated with CI.
Use ATT&CK as a vocabulary, not a substitute for analysis
MITRE ATT&CK provides a maintained knowledge base of adversary tactics and techniques across enterprise platforms. It helps describe observed or plausible behavior and check whether important parts of an attack sequence were overlooked.

It does not calculate risk. It does not know the business impact, control strength, path reachability, evidence age, or recovery objective of my system.
I map ATT&CK after describing the attack path in system terms. A path may involve valid accounts, remote services, credential access, collection, exfiltration, or inhibit-system-recovery techniques. The mapping helps detection and control review. It should not turn the threat model into a catalog of hundreds of technique IDs with no architectural context.
One path can map to several techniques. One technique can appear in several paths. Keep the system-specific path as the primary unit of analysis.
Record the ATT&CK version or access date. Technique definitions and platform coverage change.
Write risk as a chain

NIST SP 800-30 Revision 1 provides a useful structure for conducting and maintaining risk assessments. I express architecture risk as a chain:
threat source
-> threat event
-> vulnerability or predisposing condition
-> likelihood
-> impact
-> risk
-> responseA risk record should be understandable without the diagram:
risk:
id: R-012
title: Recovery copy reconnects with production identity
threat_source: operator-error-or-compromised-recovery-account
threat_event: restored system starts on a production-capable network
predisposing_conditions:
- cloned-agent-and-host-identity
- production-address-retained
- restore-nic-enabled-by-default
likelihood: moderate
impact: high
rating: high
consequences:
- duplicate-endpoint-identity
- conflicting-cluster-membership
- replayed-alerts-or-automation
- unauthorized-secret-use
response: mitigate
controls:
- link-down-first-boot
- isolated-recovery-network
- identity-regeneration-checklist
- negative-production-connectivity-tests
evidence:
- latest-isolated-restore-report
residual_risk: low-to-moderate
owner: recovery-platform-owner
review_trigger: backup-or-network-architecture-changeDo not use CVSS for an architecture risk unless the record is specifically scoring a vulnerability under CVSS. Architecture risks involve system context, threat sources, predisposing conditions, and consequences that CVSS was not designed to express.
Map controls after understanding the risk
NIST SP 800-53 Revision 5 provides a broad control catalog. It is useful for identifying control families and creating traceable implementation statements. The mapping should follow the risk analysis.

For example:
- AC controls can support least-privilege administration and separation of duties.
- AU controls can support event generation, review, time stamps, and audit protection.
- CA controls can support assessment and monitoring.
- CM controls can support configuration baselines and change control.
- CP controls can support contingency planning, backups, alternate processing, and recovery.
- IA controls can support identification, authentication, and authenticator management.
- SC controls can support boundary protection, cryptographic protection, and architecture.
- SI controls can support monitoring, flaw remediation, and integrity.
A control reference does not prove implementation. The model should link it to evidence such as a configuration readback, negative test, restore exercise, alert query, access review, or accepted change.
"Mapped to CP-9" is not recovery evidence.
Model transitions explicitly
Migration periods deserve more attention than steady state because they often create duplicate authority.

A transition model should name:
- current authority
- target authority
- dual-run purpose
- systems allowed to receive data
- systems allowed to act
- cutover gates
- rollback deadline
- credential and DNS changes
- retained recovery state
- completion criteria
transition:
id: TR-006
control: endpoint-monitoring
current_authority: legacy-manager
target_authority: enterprise-manager
phase: bounded-dual-observation
action_authority: target-only
rollback_available_until: 2026-09-10T00:00:00Z
completion_requires:
- inventory-reconciliation-pass
- telemetry-canary-pass
- legacy-producer-silence
- old-credential-revocationIf both systems can initiate response, change policy, or issue identity during migration, the attack surface may increase even though the target architecture is better.
Retired systems also remain in the model until their recovery and data-retention paths no longer affect risk.
Update by delta, then reassess the whole path
A practical maintenance process starts with the change delta:
- Which components were added, removed, upgraded, moved, or reclassified?
- Which data and administration flows changed?
- Which identities, credentials, and trust relationships changed?
- Which controls became enforced, lost authority, or remain planned?
- Which recovery paths changed?
- Which assumptions became false?

Then trace every affected attack path and risk. A local change can alter a distant risk. Moving a service to a new zone changes firewall policy, DNS, monitoring, backup reachability, administrative access, and failure domains. Replacing an identity provider changes application login, break glass, signing keys, recovery, and audit paths.
I preserve model lineage rather than overwriting history. Each assessment records its predecessor, evidence date, source revisions, changed risks, closed risks, new risks, and unchanged high risks.
A closed risk should state why it closed and cite the test that proved the condition changed. Do not delete it from history.
State limitations plainly
A useful threat model says what it did not prove.

Examples include:
- not every same-subnet path was packet-tested
- host firewalls were sampled rather than exhaustively read back
- application source code was out of scope
- physical controls were described from available records, not inspected
- backup integrity was verified but only selected services completed isolated restore
- identity policies were reviewed, but not every application uses the target provider
- ATT&CK mapping was architecture-focused, not a complete detection assessment
Limitations protect the reader from treating a model as stronger evidence than it is. They also create the next assessment plan.
Unknown is a valid result. Hidden uncertainty is not.
Open-source threat-modeling options
| Need | Open-source options | Best fit |
|---|---|---|
| Diagram-led threat modeling | OWASP Threat Dragon | Interactive data-flow diagrams and threat records for teams that prefer a graphical workflow |
| Model as code in Python | OWASP pytm | Version-controlled component and flow definitions that can generate diagrams and threats |
| YAML model and risk rules | Threagile | Architecture-as-code with generated reports and rule-based risk identification |
| General diagrams | diagrams.net, Excalidraw | Collaborative architecture and workshop diagrams, with separate structured risk records |
| Text-generated diagrams | Mermaid, PlantUML, Graphviz, D2 | Reviewable diagrams close to source, useful when layout and notation are tested in CI. |
| ATT&CK analysis | ATT&CK Navigator | Technique mapping and comparison, not system architecture by itself. |
| Risk and control records | YAML, JSON Schema, Markdown, SQLite | Small version-controlled models with deterministic validation and reports |

Threat Dragon provides a good accessible starting point. pytm and Threagile are useful when the team wants models reviewed with code. Mermaid and PlantUML are convenient for documentation, while Graphviz and D2 can produce more controlled generated layouts. Excalidraw is useful during workshops but needs a disciplined export and evidence process if it becomes authoritative.
No tool determines whether the model matches reality. That still requires inventory, interviews, configuration readback, tests, and judgment.
Validate the model in CI

A model-as-code repository can enforce mechanical quality:
model_quality:
require_unique_ids: true
require_source_dates: true
require_flow_protocol_and_direction: true
require_component_owner: true
require_risk_owner_for_high: true
require_evidence_for_closed_risk: true
require_known_implementation_state: true
reject_expired_exceptions: true
reject_orphan_flows: true
maximum_diagram_complexity:
components_per_view: 40CI can validate JSON Schema, broken references, missing owners, unsupported states, expired evidence, duplicate IDs, orphan flows, and broken links. It can render diagrams and compare generated artifacts.
CI cannot prove that a firewall rule exists on the gateway or that a backup restores. Live acceptance still has to supply evidence.
The review questions I keep using

When I review a threat model, I ask:
- What exact system state and date does this model describe?
- Which source is authoritative for each material fact?
- Where are the physical failure domains?
- Where are the logical trust boundaries?
- Which paths carry application data?
- Which paths carry administration or recovery authority?
- Which components are planned, staged, accepted, degraded, retired, or recovery-only?
- Which attack paths are plausible through those flows?
- Which controls are implemented, and what evidence proves them?
- Which risks changed since the prior model?
- Which assumptions and limitations remain?
- What change would force the next reassessment?
If the model cannot answer those questions, adding more icons will not help.
Threat modeling is change reconciliation
A threat model is often presented as something completed near the start of a project. I find it more valuable as a reconciliation process.

The rollout controller changed how deployment risk was managed. Coverage reconciliation changed the evidence behind monitoring claims. Platform retirement removed some attack paths and introduced retained recovery paths. Isolated restores reduced recovery uncertainty and exposed cloned-identity risk. The updated threat model connected those changes to the architecture.
That is the loop:
observe -> model -> decide -> implement -> verify -> recover -> reassessThe model is not finished when the diagram is exported. It is current when its facts, paths, controls, and risks match the system closely enough to support the next decision.
A stale threat model is not merely old documentation. It can direct engineering effort toward a system that no longer exists while missing the transition and recovery paths that now carry the most authority.
Model the system that actually exists. Date the evidence. Keep the limitations. Update it when reality changes.