skip to content

How do you scope a threat model to a new caseload-export feature on a twelve-year-old case-management monolith?

level: seniorimportance: should knowfreq 52%

answer

  1. model the change, not the estate
  2. the delta plus what it leans on
  3. anything the change makes a promise about
  4. bulk read is not many single reads
  5. untouched legacy flaws go to the backlog

basics

~20 s

Model the change, not the monolith. Scope covers the new behaviour, the data the change newly exposes, and every existing control the change leans on or alters. Pre-existing weaknesses in untouched code go to a backlog, not into this session.

solid answer

~50 s

I scope to the delta plus its blast radius. The delta is the export itself: a new bulk read over case records, a generated file, and wherever that file lands. The blast radius is everything whose security properties the change depends on or alters - the query path and whatever district filter it applies, the authorization check on the export action, the audit trail that now has to record bulk access, and the lifetime and reachability of the produced file. The change can widen risk without adding any component: a filter that was adequate when a caseworker read one record at a time is a very different control when the same screen emits ten thousand rows. The attacker I care about is an authenticated caseworker pulling records beyond their district; the asset is highly sensitive personal data. Legacy login, billing and reporting stay out and go on the exclusion list.

go deeper

for a junior

Be ready to say that a threat model can cover just the feature being built rather than the whole application, and that you still have to look at what the feature calls.

for a middle

Explain the delta-plus-blast-radius rule and give the test for pulling existing code in: the change depends on it for a security property, or changes an assumption it was written under.

for a senior

Demonstrate the aggregation insight - a reused per-record authorization filter becomes a mass-extraction control - and show the stop rules that let the session finish inside a sprint.

for a principal

Own the policy question: how large a change earns a model, how you stop change-scoped models from leaving permanent seams between them, and how legacy findings get routed without hijacking delivery.

### Why change-scoped modeling exists Most real threat modeling is not done on a greenfield architecture. It is done on a change to a system that already exists, is large, is old, and was never modeled. If the only accepted scope were `the whole system`, no model would ever be produced, because the first session would drown in a decade of accumulated design. Change-scoped modeling is the answer: bound the exercise to what is being built now, and be precise about how far outward that bound reaches. ### The delta and its blast radius The scope of a change model has two parts. **The delta** is what is genuinely new: new code paths, new data flows, new stored or transmitted data, new places data comes to rest. For a caseload export that is a bulk query over case records, a file-generation step, and a delivery path - a download response, an object store, or an email attachment. **The blast radius** is everything outside the delta whose behaviour the delta depends on for a security property, or whose assumptions the delta changes. This is the part inexperienced modelers skip, and it is where the real findings live. For the export it typically includes: the authorization check that decides who may invoke the export at all; the data-access layer's row-level filter, if there is one, and whether the export path goes through it or around it; the audit log, which now must record a bulk read rather than a single-record view; and session and URL handling for the produced file, which may leave the authenticated boundary entirely if the download is served from a signed or guessable link. A useful phrasing for the room: *in scope is the change and anything the change makes a promise about.* ### Behavioural widening with no structural change The most valuable thing this bound catches is a change in risk with no change in shape. Suppose the export reuses an existing report screen and adds no new endpoint. Structurally nothing was added, so a naive scope says there is nothing to model. But the control environment has moved: a district filter that is fine when a caseworker opens one child's record is a catastrophic single point of failure when the same identity can emit the entire national caseload as a spreadsheet in one action. Rate limiting that made no sense per record now matters. Detection that never fired on a page view now needs a signal for bulk extraction. Aggregation converts a low-impact authorization gap into a mass-exfiltration path, and the only way to see it is to put the reused control inside the boundary explicitly and ask what it now promises. The attacker position that drives all of this is not an anonymous internet user. It is an authenticated caseworker with a legitimate account, pulling records for districts that are not theirs - a person the perimeter will never stop and whose actions look like work. The asset is highly sensitive personal data about vulnerable people, where a single successful bulk read is unrecoverable. ### Where the line closes Three stop rules keep a change model finishing: 1. **Untouched code with pre-existing weaknesses is out.** If a legacy module has a known problem the export does not touch, record it, hand it to whoever owns the backlog, and do not expand this session into it. A change model is not an audit. 2. **A dependency comes in only when the change relies on its behaviour.** If the export reuses a legacy query builder, that builder is now inside the line because the export's safety depends on how it composes filters. If it merely runs on the same server, it is not. 3. **The exclusion list ships with the model.** The legacy login flow, the billing module, the batch reporting jobs: named, with one line each, and with a re-entry condition. A future change that touches them will find that note. ### What the deliverable looks like A good change model here is small and specific: a paragraph naming the change and its boundary, a handful of threats concentrated on authorization scope, aggregation, file lifetime and audit coverage, mitigations attached to each, and an exclusion list. It fits in one session because the boundary was made narrow on purpose - and because it was narrow, the findings are actionable rather than a generic list of everything that could ever be wrong with an aged monolith. ### The failure modes Insisting on modeling the whole monolith first guarantees the feature ships unmodeled. Scoping only the literal new lines of code misses every reused-control finding, which is where the aggregation risk hides. Treating `no new endpoint` as `no new risk` misses behavioural widening entirely. And letting the session sprawl into every legacy flaw someone remembers produces a document that lands after the release.

  • The export adds no new endpoint - it reuses an existing report screen. Does that shrink the scope?
    No. Scope follows behaviour, not structure. The reused screen now emits a bulk result set, so its authorization check, its district filter and its audit record are all making a much bigger promise than before. Those controls come into scope precisely because they were reused. A change with zero new components can still be the highest-risk change of the quarter.
  • What pulls a piece of the legacy monolith back into scope?
    One test: the change depends on that code for a security property, or the change alters an assumption that code was written under. A shared query builder that composes the district filter is in. A billing module that merely shares the same JVM is out. Stating the test out loud stops the boundary from moving on whoever argues hardest in the room.
  • Someone raises an unrelated legacy authorization flaw mid-session. What do you do?
    Capture it with enough detail to be reproducible, name an owner and route it to the backlog, then return to the change. Expanding the session turns a one-hour design review into an audit that lands after the release. The discipline is not ignoring the finding - it is refusing to let it consume the boundary you agreed at the start.

saying these in an interview costs you the question

  • Insists the whole monolith must be modeled first
  • Scopes only the new code and ignores what it calls
  • Assumes no new endpoint means no new risk
  • Treats a bulk export as the same risk as one record
  • Expands into every legacy finding and never finishes
  • Only models an anonymous outsider, never the logged-in user

context