When Should You Re-Threat-Model? A Practical Trigger List

Every team that runs a threat modeling workshop eventually asks the same follow-up question, usually a few months after the first diagram was drawn: does this still need updating? Nobody has a good answer. The diagram hasn't been touched since the session. The system underneath it has changed in a dozen small ways nobody tracked against it. And the honest response — "we're not sure, it's probably fine" — is exactly the answer that turns a threat model from a working document into a certificate you drew once and framed on the wall.

The usual fix people reach for is a calendar: review it every quarter. That sounds responsible and produces almost no value, for a reason that becomes obvious the first time you sit through one of these reviews with nothing new to say. The model needs a different kind of clock — one that runs on events in the system, not on the passage of time.

The short version: Don't schedule reviews; watch for ten specific triggers instead — a new externally reachable interface, an auth change, a new class of data, a new integration with elevated access, an architecture change that adds or removes a trust boundary, an incident that matches a branch of your tree, a new compliance driver, an ownership change, an accepted risk's review date, or a step-change in scale. The fast test for whether any given change qualifies: would the diagram itself look different? If a box, an arrow, or a trust boundary would move, revisit it. If the diagram would look identical and only the code inside a box changed, it usually doesn't. Keep a short quarterly check as a backstop for whatever nobody flagged — not a full redo, just a five-minute pass down the trigger list.

Why a calendar alone doesn't work

A quarterly review has two failure modes, and they aren't symmetric. Most quarters, nothing structurally significant happened, and the review becomes a meeting where everyone confirms the diagram still matches reality and the risk register still matches the diagram — genuinely useful the first time, close to worthless the fourth. That's the boring failure. The expensive one is the opposite: something did change, in week three of a thirteen-week quarter, and the model doesn't catch up to it until week thirteen. A new webhook integration goes live, a login flow moves behind a new identity provider, an internal admin tool gets exposed to a partner's network — and for the ten weeks between that change and the next scheduled review, the model everyone is relying on for prioritization and sign-off is quietly wrong.

The fix isn't to review more often — a monthly ritual has the same shape of problem, just compressed. It's to stop treating "has time passed" as the signal at all. The thing that actually invalidates a threat model is a change to what the system does, what it's exposed to, or what it's trusted to protect — and that happens on its own schedule, driven by shipping, not by the calendar.

The ten triggers

None of these require guesswork about what "significant" means. Each is a concrete, checkable event.

TriggerWhat actually changedExample
New external interface A new way in for anyone outside the boundaries already modeled. A public API endpoint, a webhook receiver, a new mobile deep link.
Authentication or authorization change Who can prove who they are, and what that identity is then allowed to touch. Adding SSO, changing session length, introducing a new role.
New class of data A category of information the model never assumed the system would hold. Payment details, health records, a customer's own customer data.
New integration with elevated access A third party or dependency that can now read or act on your behalf. A new SDK with device access, a Slack app with a write scope, a new vendor with a service account.
Architecture change that moves a trust boundary Something that used to be internal is now reachable from outside it, or vice versa. Splitting a monolith, moving a job from an internal queue to a public-facing service.
An incident or near miss A real event that tests a branch of the tree, whether it happened to you or a comparable company. A sector breach that matches one of your assumptions; an internal near miss caught by luck.
A new compliance driver An external party is now going to ask what you modeled and why. A customer security questionnaire, a new certification, a new regulation in a market you're entering.
Ownership change The person who held the context behind the model's assumptions is no longer the one watching for these triggers. The engineer who ran the original workshop leaves or changes teams.
An accepted risk's review date arrives A previously accepted risk was conditional on facts that may no longer hold. "Low priority because this feature has forty users" — and now it has four thousand.
A step-change in scale or attractiveness The same system, but now a more valuable target to attack. A funding announcement, a large new customer, sudden press coverage.

A handful of these overlap in practice — a new integration is often also a new external interface, an architecture change often moves data classes around with it — and that's fine. The list isn't meant to be mutually exclusive categories for a spreadsheet. It's meant to be a short, memorable set of questions someone can hold in their head while reading a PR or a design doc.

The fast test: what changed, versus how it changed

Most day-to-day changes to a codebase are refactors: the same inputs, the same outputs, the same trust boundaries, different code underneath. None of the ten triggers fire for those, and they shouldn't — re-running a threat model on every pull request would make the practice unsustainable, which is its own way of killing it.

The test that separates the two: if you redrew the data flow diagram today, would a box, an arrow, or a trust boundary move? A new caller, a new data store, a new external dependency, a boundary that used to sit between two things and no longer does — any of those changes the picture. A change to how a function is implemented, with the same callers, the same data, the same boundaries either side of it, doesn't. This is a question most engineers can answer for their own change in under a minute, which is exactly why it works as a filter someone applies routinely rather than a judgment call escalated to whoever ran the original workshop.

Attach it to a ritual, not a document

A trigger list that lives in a wiki page nobody opens does nothing. It only works pinned somewhere a change already has to pass through — a question in the pull request template, a section in the design doc your team already writes, or, per the shift-left argument, a step at design time rather than a step after the fact. The same applies to who's watching: if your team has a named practice owner rather than a dedicated security function, the trigger list is the concrete thing that role is actually checking for, not an abstract mandate to "keep an eye on security."

When a trigger fires, the update should be scoped to what changed, not a full re-run. A new webhook receiver needs its own entry on the diagram, its own pass through STRIDE, and a look at what it now touches — not a redo of the entire model. Matching the size of the update to the size of the trigger is what keeps this sustainable; treating every trigger as a reason to reopen the whole model is a fast way to make people stop reporting them.

The backstop: a five-minute quarterly check, not a redo

Event-driven triggers have one real weakness: they depend on someone noticing and connecting the dots, and sometimes nobody does. A calendar still earns a place here, just a much smaller one than the quarterly-workshop version. Once a quarter, spend five minutes against the same ten-item list: did any of these happen in the last three months that didn't produce an update? Did an accepted risk's review date pass unnoticed? It isn't a re-modeling session. It's a check for gaps in the event-driven process, which is a different and much cheaper thing than the process itself.

A worked example

A mid-sized SaaS product, two quarters after its first workshop:

  • Week 4: a new webhook integration ships, giving a partner service push access to order events. Trigger: new external interface, new integration with elevated access. The team adds the webhook as a new element, runs STRIDE against just that addition, and adds two new entries to the register — not a full re-run.
  • Week 9: the engineer who ran the original workshop moves to a different team. Trigger: ownership change. The design-doc template's security section is handed to their replacement explicitly, rather than left to drift to whoever happens to notice it's unowned.
  • Week 15: a competitor in the same space discloses an OAuth token-leakage incident. Trigger: sector incident matching a branch of the tree. The team spends twenty minutes checking whether their own OAuth flow shares the same assumption the competitor's didn't test, and confirms it doesn't — a cheap check that closes the question rather than leaving it as background anxiety.
  • Week 20: an accepted risk from the original workshop — "acceptable because this admin panel has twelve internal users" — hits its review date. The panel now has ninety users across two customer support teams. The acceptance is revisited and reclassified as a fix, per the prioritization pass that produced it.
  • End of quarter: a five-minute check against the trigger list confirms nothing else fired unnoticed. Total time spent across the quarter: under two hours, none of it a full re-run.

Where this goes wrong

  • Treating "we haven't had time" as a reason to skip a real trigger. A missed trigger doesn't queue itself for later — it just leaves the model wrong until something else forces the question, usually an incident.
  • Full re-runs for small triggers. Re-modeling the entire system because one webhook shipped trains people to under-report triggers, because reporting one feels disproportionately expensive.
  • Burying the list in a document nobody consults. A trigger list is only as good as the ritual it's attached to. Unattached, it's a page someone wrote once and nobody rereads until an audit asks for it.
  • No named owner watching for them. Ten triggers and nobody whose job it is to notice them is the same as zero triggers — the list existing on paper isn't the same as anyone checking it.
  • Confusing "nothing on the list fired" with "nothing changed." The list is a practical filter, not a complete theory of risk. It catches most of what matters cheaply; it isn't a guarantee that a genuinely novel kind of change won't slip past it.

A threat model that's revisited on real triggers, scoped to what actually changed, stays closer to true for less total effort than one reviewed on a calendar and mostly rubber-stamped. The measure of whether this is working isn't how often the model gets touched — it's whether, when something in the system genuinely changes, the model changes with it before anyone has to ask.

Regulated environments tend to generate compliance-driven triggers on a predictable cycle of their own — see threat modeling for fintech and for healthcare for what typically forces a revisit there. The DFD template is a reasonable starting point if the model this list is meant to keep current doesn't exist yet.

Keep one model the whole team checks against, not a document that ages out of date

ThreatTree keeps your diagram, your STRIDE pass, and your risk register linked together, so updating one element after a real trigger doesn't mean starting over — and accepted risks carry their own review dates instead of aging silently.

Get started free

Not ready to sign up? Get new threat-modeling guides by email instead.