Threat Modeling OTP Flows · Chapter 1 of 6
Building the threat model: assets, actors, trust boundaries
Draw the flow before you defend it. A one-page model of what is valuable, who wants it and where trust changes hands.
A threat model is a structured answer to four questions: what are we building, what can go wrong, what are we going to do about it, and did we do a good job. Teams that skip the first question jump straight to controls they have read about elsewhere and end up defending the wrong door. This chapter builds the first artefact of the series: a single-page model of a typical OTP login and step-up flow, which every later chapter extends.
We will use a fictional organisation throughout the series, Pinecrest Health, a regional clinic network whose patient portal lets people view lab results, message clinicians and update payment details. Its login uses a password plus a one-time code, with a TOTP app as the preferred factor and a phone-delivered code as fallback. Ilse Brandvold, Pinecrest’s application security lead, owns the model and reviews it quarterly.
Start with assets, not attacks
Assets are the things an attacker wants or the things whose loss would hurt you. In an OTP flow they fall into three groups. Data assets: the TOTP seeds, the session tokens, the phone numbers and the audit log. Capability assets: the ability to sign in as a patient, to change a phone number, to add a payment card, to trigger outbound messages. Economic assets: your messaging budget and your support team’s time. Listing them explicitly forces the question of which ones a given control protects.
seed store— symmetric secrets; theft mints codes for every enrolled user.session— the real prize of most account takeovers.phone-number field— whoever controls it controls the fallback factor.send endpoint— a capability that costs money every time it is called.recovery flow— the path that bypasses everything else when used.
Notice that the send endpoint is an asset in its own right. It is easy to model it only as part of the login flow, but an attacker who never intends to sign in can still abuse it, and chapter 5 is entirely about that case.
Actors and their capabilities
Name actors by capability rather than by stereotype. A remote opportunist has leaked password lists and automation but no access to any victim device. A targeted phisher can stand up a lookalike domain and a relay proxy and will interact with one victim in real time. A telecom social engineer can persuade or bribe a carrier store employee to move a number. An insider has legitimate access to your support tooling. A fraud ring is financially motivated to call your send endpoint at scale. Each actor maps to different chapters and different controls.
Trust boundaries are where to look
A trust boundary is any point where data passes between components that are controlled by different parties or run at different privilege levels. In the diagram there are at least four: between the browser and your edge, between the auth service and the seed store, between your send endpoint and the third-party gateway, and between the gateway and the phone network. The last one matters most for phone-delivered codes because you do not control it at all: once the message leaves the gateway, its confidentiality depends on carriers and on whoever holds the SIM.
For each boundary, ask what crosses it, what the receiving side assumes about it, and how that assumption could be violated. The auth service assumes the code it receives was typed by the person who started the login; chapter 3 shows how relay breaks that. The send endpoint assumes requests represent real users who want codes; chapter 5 shows how pumping breaks that. The handset is assumed to be in the user’s pocket; chapter 2 shows how SIM swap breaks that.
Attacker view
Where I look first
- The recovery flow, because it bypasses every factor.
- Any endpoint that sends a message without proof of a prior step.
- Support tooling that can change a phone number.
- Error messages that reveal whether a number is enrolled.
Defender view
What the model must record
- Every boundary with its assumption written as one sentence.
- The owner of each asset and each control.
- Which actors each control is meant to stop.
- A date for the next review.
A lightweight method
You do not need a heavyweight framework to get value. A workable cadence for a team of Pinecrest’s size is a ninety-minute session with the engineers who own the flow, a whiteboard version of the data-flow diagram, and a shared document with one row per threat. STRIDE — spoofing, tampering, repudiation, information disclosure, denial of service, elevation of privilege — is useful as a checklist to prompt ideas at each boundary, but the output should be in plain language that a new engineer can read in ten minutes.
threat: Phone number changed via support call
asset: phone-number field → fallback factor
actor: telecom social engineer / insider
boundary: support tool → account record
assumption: caller is the account holder
severity: high (see chapter 6 rubric)
controls: callback to old number, 48 h hold, notify all channels
owner: I. Brandvold · review 2026-12-15The output of the first session at Pinecrest was twenty-three threats, of which six were judged high or critical. That number is an illustrative example, not a benchmark; what matters is that each threat had an owner and a next step before the meeting ended. The remaining chapters take the most important classes one at a time and show how the entries evolve.
Common gaps in first drafts
First drafts tend to over-index on cryptography and under-index on people and money. Seeds and HMACs get careful attention while the support desk, the billing implications of the send endpoint and the recovery flow get a single line each. Another frequent gap is treating the third-party message gateway as a trusted component; it is a vendor with its own staff, outages and incidents, and the model should say what happens if it misbehaves. Finally, drafts often forget that the attacker can be the account holder: a user who wants to share an account or evade a ban is a valid actor with different goals.
By the end of this chapter you should be able to draw your own flow, list its assets, name its actors by capability, and point to every trust boundary. That diagram is the map for everything else. Without it, controls are guesses; with it, they become answers to specific, written questions.
// bench check
0/3 correct · 0 answered
1. Why is the send endpoint modelled as an asset on its own?
2. What is a trust boundary?
3. Which actor description is most useful in a model?