[{"data":1,"prerenderedAt":308},["ShallowReactive",2],{"writing-threat-modeling-that-people-use":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"updated":10,"tags":11,"draft":6,"body":15,"_type":302,"_id":303,"_source":304,"_file":305,"_stem":306,"_extension":307},"/writing/threat-modeling-that-people-use","writing",false,"","How to run a threat model people actually use","Threat modeling fails when it produces a document instead of decisions. A practical walkthrough of scope, trust boundaries, STRIDE, and useful output.","2026-03-17",[12,13,14],"threat-modeling","security-architecture","secure-design",{"type":16,"children":17,"toc":292},"root",[18,26,31,38,43,68,73,79,84,89,95,100,105,110,116,121,186,191,196,202,207,250,255,260,266,271,276,282,287],{"type":19,"tag":20,"props":21,"children":22},"element","p",{},[23],{"type":24,"value":25},"text","Most threat models fail the same way. A team books two hours, fills a whiteboard, someone types it into a wiki page, and nobody opens it again. The exercise was real and the output was useless, because a threat model that does not change what gets built is just a meeting.",{"type":19,"tag":20,"props":27,"children":28},{},[29],{"type":24,"value":30},"The fix is not a better template. It is being clear about what the output is supposed to be: a small number of decisions someone owns, not a catalogue of everything that could theoretically go wrong.",{"type":19,"tag":32,"props":33,"children":35},"h2",{"id":34},"the-four-questions",[36],{"type":24,"value":37},"The four questions",{"type":19,"tag":20,"props":39,"children":40},{},[41],{"type":24,"value":42},"Adam Shostack's framing is still the most useful structure, because it is short enough to remember:",{"type":19,"tag":44,"props":45,"children":46},"ol",{},[47,53,58,63],{"type":19,"tag":48,"props":49,"children":50},"li",{},[51],{"type":24,"value":52},"What are we building?",{"type":19,"tag":48,"props":54,"children":55},{},[56],{"type":24,"value":57},"What can go wrong?",{"type":19,"tag":48,"props":59,"children":60},{},[61],{"type":24,"value":62},"What are we going to do about it?",{"type":19,"tag":48,"props":64,"children":65},{},[66],{"type":24,"value":67},"Did we do a good job?",{"type":19,"tag":20,"props":69,"children":70},{},[71],{"type":24,"value":72},"Teams reliably spend all their time on question two and skip questions three and four. That is the failure. Question three is where the value is, and question four is what stops the model going stale the moment the architecture moves.",{"type":19,"tag":32,"props":74,"children":76},{"id":75},"scope-it-small-enough-to-finish",[77],{"type":24,"value":78},"Scope it small enough to finish",{"type":19,"tag":20,"props":80,"children":81},{},[82],{"type":24,"value":83},"The most common practical mistake is scope. \"Threat model the platform\" produces nothing. \"Threat model the flow where an external user uploads a file and we process it\" produces a list you can act on by Friday.",{"type":19,"tag":20,"props":85,"children":86},{},[87],{"type":24,"value":88},"Pick a flow, not a system. One entry point, one path through, one set of data. If the discussion keeps drifting to adjacent services, that is a signal you picked the wrong boundary — note it and come back to it separately.",{"type":19,"tag":32,"props":90,"children":92},{"id":91},"draw-the-thing-badly",[93],{"type":24,"value":94},"Draw the thing, badly",{"type":19,"tag":20,"props":96,"children":97},{},[98],{"type":24,"value":99},"You need a diagram, but you do not need a good one. Boxes for processes, arrows for data, cylinders for storage, and — the only part that really matters — lines where trust changes.",{"type":19,"tag":20,"props":101,"children":102},{},[103],{"type":24,"value":104},"A trust boundary is any point where data crosses from somewhere you control less to somewhere you control more. The internet to your load balancer. Your frontend to your API. Your API to a third-party service. One service's credentials to another service's database.",{"type":19,"tag":20,"props":106,"children":107},{},[108],{"type":24,"value":109},"Almost every finding worth having lives on one of those lines. If your diagram has no trust boundaries drawn on it, you have not finished drawing it.",{"type":19,"tag":32,"props":111,"children":113},{"id":112},"stride-applied-per-boundary",[114],{"type":24,"value":115},"STRIDE, applied per boundary",{"type":19,"tag":20,"props":117,"children":118},{},[119],{"type":24,"value":120},"STRIDE gives you six prompts to walk each boundary with:",{"type":19,"tag":122,"props":123,"children":124},"ul",{},[125,136,146,156,166,176],{"type":19,"tag":48,"props":126,"children":127},{},[128,134],{"type":19,"tag":129,"props":130,"children":131},"strong",{},[132],{"type":24,"value":133},"Spoofing",{"type":24,"value":135}," — can someone claim to be a party they are not?",{"type":19,"tag":48,"props":137,"children":138},{},[139,144],{"type":19,"tag":129,"props":140,"children":141},{},[142],{"type":24,"value":143},"Tampering",{"type":24,"value":145}," — can data be modified in transit or at rest?",{"type":19,"tag":48,"props":147,"children":148},{},[149,154],{"type":19,"tag":129,"props":150,"children":151},{},[152],{"type":24,"value":153},"Repudiation",{"type":24,"value":155}," — can someone deny an action, and would we be able to prove otherwise?",{"type":19,"tag":48,"props":157,"children":158},{},[159,164],{"type":19,"tag":129,"props":160,"children":161},{},[162],{"type":24,"value":163},"Information disclosure",{"type":24,"value":165}," — can data reach somewhere it should not?",{"type":19,"tag":48,"props":167,"children":168},{},[169,174],{"type":19,"tag":129,"props":170,"children":171},{},[172],{"type":24,"value":173},"Denial of service",{"type":24,"value":175}," — can availability be degraded cheaply?",{"type":19,"tag":48,"props":177,"children":178},{},[179,184],{"type":19,"tag":129,"props":180,"children":181},{},[182],{"type":24,"value":183},"Elevation of privilege",{"type":24,"value":185}," — can someone acquire rights they were not granted?",{"type":19,"tag":20,"props":187,"children":188},{},[189],{"type":24,"value":190},"The value of the acronym is not completeness. It is that it forces you past the two threats everyone thinks of first. Teams naturally find information disclosure and elevation of privilege. Repudiation is almost always the one nobody considered, and it is the one that hurts during an incident when you cannot reconstruct who did what.",{"type":19,"tag":20,"props":192,"children":193},{},[194],{"type":24,"value":195},"Work boundary by boundary rather than threat by threat. Six prompts against four boundaries is twenty-four short questions, most answered in a sentence. That is a tractable ninety minutes.",{"type":19,"tag":32,"props":197,"children":199},{"id":198},"the-output-is-a-decision-list",[200],{"type":24,"value":201},"The output is a decision list",{"type":19,"tag":20,"props":203,"children":204},{},[205],{"type":24,"value":206},"For every threat you keep, record one of four outcomes:",{"type":19,"tag":122,"props":208,"children":209},{},[210,220,230,240],{"type":19,"tag":48,"props":211,"children":212},{},[213,218],{"type":19,"tag":129,"props":214,"children":215},{},[216],{"type":24,"value":217},"Mitigate",{"type":24,"value":219}," — we are adding a control. Who owns it, and where does it live?",{"type":19,"tag":48,"props":221,"children":222},{},[223,228],{"type":19,"tag":129,"props":224,"children":225},{},[226],{"type":24,"value":227},"Accept",{"type":24,"value":229}," — we understand it and we are choosing to carry it. Who accepted it?",{"type":19,"tag":48,"props":231,"children":232},{},[233,238],{"type":19,"tag":129,"props":234,"children":235},{},[236],{"type":24,"value":237},"Transfer",{"type":24,"value":239}," — someone else carries it, and we know how.",{"type":19,"tag":48,"props":241,"children":242},{},[243,248],{"type":19,"tag":129,"props":244,"children":245},{},[246],{"type":24,"value":247},"Eliminate",{"type":24,"value":249}," — we are removing the feature or path that creates it.",{"type":19,"tag":20,"props":251,"children":252},{},[253],{"type":24,"value":254},"Accept is a legitimate answer and it should be written down with a name against it. An accepted risk that was never recorded turns into a surprise later, and the argument about whether anyone knew is worse than the risk itself.",{"type":19,"tag":20,"props":256,"children":257},{},[258],{"type":24,"value":259},"Anything marked mitigate becomes a ticket in the same tracker as everything else. A finding that lives only in a security document does not get scheduled.",{"type":19,"tag":32,"props":261,"children":263},{"id":262},"do-it-at-the-right-time",[264],{"type":24,"value":265},"Do it at the right time",{"type":19,"tag":20,"props":267,"children":268},{},[269],{"type":24,"value":270},"Before implementation, after the design is real enough to argue about. Too early and you are modelling a system nobody has committed to. Too late and every mitigation competes with a shipping date it will lose against.",{"type":19,"tag":20,"props":272,"children":273},{},[274],{"type":24,"value":275},"A useful trigger: run it when a design introduces a new trust boundary. New external integration, new data class, new authentication path, new service that holds credentials for another. Those are the changes that alter the shape of the attack surface, and they are cheap to reason about on a diagram and expensive to fix in production.",{"type":19,"tag":32,"props":277,"children":279},{"id":278},"revisit-it-when-the-boundaries-move",[280],{"type":24,"value":281},"Revisit it when the boundaries move",{"type":19,"tag":20,"props":283,"children":284},{},[285],{"type":24,"value":286},"Question four — did we do a good job — is not a retrospective on the meeting. It is a check against reality. When the architecture changes, the model is stale. When an incident happens, the model either predicted it or missed it, and both are informative.",{"type":19,"tag":20,"props":288,"children":289},{},[290],{"type":24,"value":291},"A threat model is not a document you produce once and archive. It is a description of where your system trusts things, and that description should be roughly as current as your architecture diagram — which, admittedly, sets a low bar in most organisations.",{"title":7,"searchDepth":293,"depth":293,"links":294},2,[295,296,297,298,299,300,301],{"id":34,"depth":293,"text":37},{"id":75,"depth":293,"text":78},{"id":91,"depth":293,"text":94},{"id":112,"depth":293,"text":115},{"id":198,"depth":293,"text":201},{"id":262,"depth":293,"text":265},{"id":278,"depth":293,"text":281},"markdown","content:writing:threat-modeling-that-people-use.md","content","writing/threat-modeling-that-people-use.md","writing/threat-modeling-that-people-use","md",1785577357169]