How would you threat-model a consumer app that handles accounts, payments and personal data?
Predict first
Which control best protects the integrity of an account balance against a modified app?
// A: jailbreak detection in the app
// B: server-side authorisation and enforcement of balance rules
// C: hiding the API URL in the binary
- A
- B
- C
Mental model. A threat model is a home-security survey: list what is valuable, walk the property to find doors and windows, ask who might try them and with what tools, then spend on the locks that matter most and write down which risks you accept.
Start with assets: what is worth stealing or breaking (credentials and tokens, payment details, personal data, the integrity of orders or balances, availability, the brand). Draw the system and its trust boundaries: the app on a device the user (and attacker) controls, the network, your backend and its third-party services, push and deep-link entry points, and shared storage (backups, the pasteboard, extensions). Then enumerate threats at each boundary, for example with STRIDE: Spoofing (stolen tokens, phishing, a fake client, a hijacked custom scheme), Tampering (modified app, altered requests, a malicious deep link), Repudiation (a user denies an action: needs server-side audit logs), Information disclosure (logs, backups, screenshots, a proxy on a hostile Wi-Fi, secrets in the binary), Denial of service (abusive clients, expensive endpoints) and Elevation of privilege (an API that trusts the client’s claim of who it is or what it may do). Name the attackers realistically: a curious user on their own device, an opportunistic thief with the phone, a remote attacker on the network, a malicious app on the same device, a scripted fraud ring, and a compromised dependency; their capabilities decide which mitigations matter.
For each credible threat choose a mitigation and place it where it works. Identity and sessions: short-lived tokens, refresh handled in one place, tokens in the Keychain, re-authentication with biometrics for sensitive actions (bound to Keychain access control, not a boolean). Transport: TLS with ATS, optional pinning with a rotation plan. Data at rest: minimum collection, file protection and Keychain classes, no secrets in the binary or logs, deletion on sign-out. Client integrity: App Attest as a signal for high-value endpoints, detection as a signal, never the gate. Inputs: validate deep links and every server response, sanitise web content. Backend: authorise every request server-side, rate-limit, monitor and alert, and keep business rules on the server. Supply chain: audit SDKs and privacy manifests, pin dependency versions, review updates. Then rank by risk (likelihood × impact) and by cost, write down the accepted residual risks (for example “a jailbroken device owner can read their own data”), and decide how you will detect and respond: logging, incident runbooks, key rotation, remote kill switches and a disclosure process. Revisit the model when features change (a new payment flow, a new SDK), test the assumptions (penetration testing, a bug bounty, red-team exercises) and keep the output as a short living document that the team actually uses in design reviews.
The client is under the attacker’s control, so the check that matters must run on the server. The others are speed bumps.
| Typical threat | Where the mitigation lives | |
|---|---|---|
| Stolen token | session theft, replay | short-lived tokens, Keychain, server revocation |
| Fake or modified client | fraud, scripted abuse | App Attest signal, server-side authorisation, rate limits |
| Hostile network | interception | TLS and ATS, optional pinning with rotation |
| Data on the device | backups, logs, screenshots | data minimisation, protection classes, private logging |
| Malicious link | action injection, scheme hijack | allow-list validation, confirmation, universal links and PKCE |
Common traps
- Listing techniques without attackers or assets. You end up with pinning and jailbreak checks and an unprotected backend; start from what is at risk.
- Putting the defences on the client. The attacker controls the client; the strongest controls are server-side authorisation and monitoring.
They might follow up with
- What does STRIDE give you? A checklist of threat types to apply at each trust boundary.
- When do you update the model? When assets, flows or dependencies change: a new payment path, SDK or API.