TRT
Sign in
Networking

Threat Modeling Starts With Assets and Boundaries

Threat modeling is a structured way to ask how a system could be misused or attacked.

The Runtime Theory Team5 min read#threat-modeling#trust-boundaries#attack-surface

Threat modeling is a structured way to ask how a system could be misused — before someone else asks the same question with your data. It is not a penetration test and not a compliance checklist: it is a short, repeatable exercise that produces a list of plausible attacks, the boundary where each one would have to succeed, and the person responsible for the control. Done well it takes an afternoon; skipped, the same discussion happens during an incident instead.

Assets, actors, data flows, boundaries

Four nouns are enough to start:

  • Assets — what an attacker wants: credentials, personal data, payment state, signing keys, admin capability, availability itself.
  • Actors — who wants it: an anonymous internet caller, an authenticated but curious user, a compromised dependency, a malicious tenant, an insider with production access.
  • Data flows — the paths data and commands actually travel, drawn from the real deployment diagram, not the architecture slide.
  • Trust boundaries — where assumptions change: browser to server, service to database, tenant to tenant, production to third party, your account to your cloud provider.

A boundary is wherever you must stop assuming and start verifying. That definition is broader than the network edge: a process boundary, a queue consumer, or an internal service that receives data from a less-trusted one all qualify. Most real gaps sit one hop inside the perimeter — an internal API that trusts any caller because "we're behind the load balancer."

Draw the path, then interrogate each crossing

Take a concrete feature — file upload — and draw it honestly:

text
[ browser ] --HTTPS--> [ API ] --put--> [ object store ]
                           |
                           +--enqueue--> [ worker ] --fetch--> [ image processor ]
                            ^                |
                    trust boundary      trust boundary
                    (user input)        (worker privileges)

Every crossing raises a specific, answerable set of questions:

  1. Who authenticates this hop, and what exactly do they get to do after it?
  2. What does the caller control here — filename, MIME type, size, URL, timing, contents?
  3. What is validated before the value is used by the next component?
  4. What privileges does the next component run with?
  5. What happens when this hop is slow, malicious, or absent?

For this upload flow the abuse cases write themselves: a .jpg that is actually an SVG with an embedded script (stored XSS once it is served back); ../../etc/passwd as a filename (path traversal against a naive path join); a 4 GB "image" (denial of service by disk exhaustion — so enforce the size limit while streaming, not after buffering); a decompression bomb inside a zip or a 60,000 × 60,000 pixel PNG (CPU and memory exhaustion in the processor); and a worker that runs with credentials for the whole bucket because "it needs to read the file it wrote a moment ago."

Turn each threat into a question with an owner

A lightweight taxonomy keeps the questions from collapsing into generic worries. For each boundary, ask the six classes:

ClassThe questionTypical control
SpoofingCan the caller pretend to be someone else?mutual auth, session validation
TamperingCan data change in transit or at rest?signatures, TLS, integrity checks
RepudiationCan someone deny an action they took?audit logs with actor and object
Information disclosureCan data be read by the wrong party?scoping, encryption, redaction
Denial of serviceCan it be made unavailable?rate limits, quotas, size caps
Elevation of privilegeCan it do more than intended?least privilege, explicit authz

The output is not a matrix — it is five to fifteen sentences of the form "an attacker without a session can reach this endpoint, and the control is X, owned by Y." Anything more detailed than that stops being read.

Make it survive contact with the codebase

A threat list without mitigations, owners, and tests becomes paperwork. Three habits keep it alive:

  • Timebox it and attach it to a change. A 60–90 minute session on a new feature, led by someone who did not write it, produces more than a multi-day review of an entire system.
  • Convert findings into tests. "Filename is attacker-controlled" becomes an integration test that uploads ../../etc/passwd and asserts rejection; "authorization at the resource" becomes the second-user test described in security follows data and authority. Tests are what stops the same threat from coming back after a refactor.
  • Revisit on trigger, not only on a calendar. Re-run the model when the architecture changes, a new external exposure appears, sensitive data is added, a third party joins the path, or an incident reveals an assumption was wrong. A quarterly glance plus those triggers is a realistic cadence for most teams; an annual "security review" is not.

Where this bites in production

  • The perimeter you drew is not the perimeter that exists. Internal services, CI jobs, and admin tools are boundaries too, and they are where over-privileged credentials turn a single compromise into an account-wide one.
  • Generic checklists miss the local risk. The dangerous path is usually specific to your deployment — a webhook callback with no signature check, a tenant ID taken from the request instead of the session, an object key built from user input.
  • Undiagrammed features are unmodeled features. The flow nobody drew (password reset, CSV export, webhook retry) is the one with an unanswered boundary.
  • Ownership is the deliverable. A threat with no owner and no test will be rediscovered by the next engineer — and by anyone reading your error messages.

Companion reading: security follows data and authority across boundaries and treat browser input as data at every boundary. Further reading: OWASP: Threat Modeling.

Spotted a mistake or something broken? Report a problem

Not started

Sign in to save your learning progress.

Sign in to save