ATALAIA
  1. Home
  2. Resources
  3. Blog
  4. Keep your threat model in layers
Design · Opinion

Keep your threat model in layers

A single threat model document is out of date the week after the workshop. Split it into layers and update each one when that layer changes.

4 min readAtalaia team

Threat modelingArchitectureProcess

Most threat models are written once. A team books a workshop, draws the system, lists threats with STRIDE, and produces a document. It is often a good document. Six months later the product has new integrations, a new deployment path and two new roles, and the document describes a system that no longer exists.

Our position is that the problem is not discipline. It is shape. A single document mixes things that change at very different speeds and are owned by different people. Split it into layers and it can keep up.

Why one document fails

Think about who knows what in a typical organisation. Product knows which flows move money and which data is sensitive. Architects know the services and boundaries. Developers know the code paths. Platform knows the pipeline and its tokens. Operations knows what is actually running and who can reach it.

A single threat model asks all of them to update one artefact. In practice, nobody does, because no single change feels big enough to reopen the whole thing. So the model drifts until the next audit or incident forces a rewrite.

There is a second problem. A threat at one level often has its cause at another. An authorisation bug in code may exist because the design never stated who owns an object. A supply chain risk in the pipeline may matter only because the runtime has broad cloud permissions. A flat list of threats hides those links.

The five layers

We keep threat models in five layers. Each one has an owner and a clear trigger for an update:

LayerWhat it holdsOwnerUpdate when
Business and processValuable assets, critical flows, abuse goals, actorsProductA new feature, market or role
ArchitectureServices, data stores, trust boundaries, data flowsArchitects or tech leadsA new service, integration or store
CodeEntry points, authorisation logic, parsers, crypto useService teamsChanges to sensitive paths
PipelineRunners, tokens, actions, dependencies, signingPlatformA new workflow, secret or deploy target
RuntimeIdentities, network reach, exposed ports, detectionOperations or SRENew infrastructure or permission changes

Each layer is small enough to review in an hour, and each one changes when its owner already has the context in their head.

Threats that cross layers

The layers are not separate documents that ignore each other. The value is in the links. A threat is recorded at the layer where it is realised and linked to the layers that enable or limit it. For example:

  1. BusinessGoal: a customer reads another customer's statements.
  2. ArchitectureStatements service shares a database across tenants, filtered by a tenant id.
  3. CodeThe export endpoint takes a statement id and must check its tenant on every call.
  4. RuntimeExport calls are logged with tenant and actor, and alert on cross-tenant patterns.

Now a change in any layer tells you what to recheck. If the architecture moves to per-tenant databases, the code-level check becomes defence in depth rather than the only control. If someone adds a bulk export, the code layer owner sees that a business-layer goal depends on it.

The usual objections

"This is more work." It is less work spread more evenly. Updating one layer after a change takes minutes. Rewriting a whole model every year takes days and is never quite finished.

"Our teams will not keep it up." They will not keep up a document. They will keep up a section that is triggered by changes they already make, especially if the pull request template asks the question.

"We do not have a security team to run it." The layers are owned by the people who know them. Security, if you have it, reviews the links and the gaps, which is where expertise matters most.

What we would do

  • Start with the business layer. Five to ten abuse goals in plain language are enough.
  • Draw the architecture layer on one page with trust boundaries marked.
  • For code, pipeline and runtime, start with only the parts linked to those goals. Do not try to model everything.
  • Store each layer as text in the repository closest to its owner, and link them by id.
  • Add a line to pull request and change templates: "Does this change a threat model layer?"
  • Review the links once a quarter. Unlinked goals and orphaned controls are the agenda.

This is the idea behind the layered threat model we are building into the tower: each layer updates from the systems that already describe it, and the links show what a change touches. You do not need a platform to start, though. A folder of short text files and a habit will get you most of the way down the line.

Where this sits on the line

In the tower (in development):

Talk it through

A 30-minute call. No slides, no price list, and a next step either way.