Threat model
A written map of who might attack your app, how they would try it, and which of those attacks you actually plan to stop.
See it
What it is
A threat model is four questions written down: what are we building, what can go wrong, what are we doing about it, and did we do a good enough job (Adam Shostack's framing). The output is a short document, not a certificate: a sketch of your system, a list of the ways in (login, uploads, webhooks, the admin panel, that third-party script in your head tag), and a decision per item: fix, mitigate, accept, or ignore.
Reach for it before you build the risky part, not after the pentest report lands. Thirty minutes at a whiteboard catches design mistakes no scanner ever will, because scanners find bad code and threat models find bad assumptions. STRIDE (spoofing, tampering, repudiation, information disclosure, denial of service, elevation of privilege) is the usual prompt list when you are staring at a blank page.
The classic mistake is modeling the wrong attacker. For most apps the realistic threat is an automated bot scanning for exposed .env files and a bored logged-in user changing an ID in a URL, not a nation state. Model the attacker who actually shows up, and write down what you decided to accept, because an undocumented accepted risk is indistinguishable from an oversight six months later.
Ask AI for it
Write a threat model for this app before we harden anything. Produce four things: (1) a plain data-flow sketch listing every entry point (public routes, auth endpoints, file uploads, webhooks, third-party scripts, admin surfaces) and every trust boundary they cross; (2) for each entry point, the realistic attacks using STRIDE as the checklist; (3) a ranking by likelihood times blast radius; (4) for the top ten, one concrete mitigation each, naming the file or config it belongs in, plus an explicit 'accepted, and here is why' line for anything we are not fixing. Assume the attacker is an automated scanner and a curious logged-in user, not a nation state.