Every threat modeling method starts with the same question: what are we working on? The usual answer is a data flow diagram. It is a simple picture with five kinds of elements, and it is the most useful hour you can spend before a security review, because most threats live where data crosses from one level of trust to another.
This guide shows how to draw a data flow diagram (DFD) for threat modeling, how to place trust boundaries, and how to walk the diagram with STRIDE. The example is a feature almost every product has: users uploading a profile photo.
The four questions
A practical threat model answers four questions, popularized by Adam Shostack and the Threat Modeling Manifesto:
- What are we working on?
- What can go wrong?
- What are we going to do about it?
- Did we do a good enough job?
The data flow diagram answers the first one. STRIDE helps with the second. The notes and tickets you attach to the diagram answer the third, and a review a few weeks later answers the fourth.
The elements of a data flow diagram
| Element | What it is | Usual shape |
|---|---|---|
| External entity | A person or system outside your control: a user, a partner API | Rectangle |
| Process | Code you run that transforms or moves data | Circle or rounded shape |
| Data store | Where data rests: a database, a bucket, a queue, a log | Two parallel lines or a cylinder |
| Data flow | Data moving between two elements | Arrow labeled with the data |
| Trust boundary | Where the level of trust changes | Dashed line or a zone around elements |
Two rules make a DFD useful for security. Label every flow with the data it carries, not only the protocol: photo + session token tells a reviewer far more than HTTPS. And never connect two data stores or two external entities directly: data only moves through a process, which is where you can check it.
The example: profile photo upload
Users upload a profile photo from the browser. The web API checks their session and stores the raw file in a private bucket. An upload processor picks it up, sends the bytes to a third-party malware scanning API, re-encodes the image, strips its metadata, writes the clean version back to the bucket and records the photo URL in the users database.
There are four trust zones: the internet, our application tier, our data tier, and the third-party scanner. Drawn as a DFD:
Diagram contents
- Trust zone: internet
- Trust zone: app tier
- Trust zone: data tier
- Trust zone: third party
- User's browser
- Web API
- Upload processor
- Photo bucket (private)
- Users DB
- Malware scan API
- photo + session token
- raw photo
- clean image, no metadata
- file bytes
- verdict
- photo URL + status
Count the flows that cross a zone boundary: browser to API, API to bucket, bucket to processor and back, processor to the scanner and back, processor to the database. Those are the places to spend your time.
Walk the diagram with STRIDE
STRIDE names six kinds of threats. Microsoft's "STRIDE per element" approach checks each element only for the threats that apply to its type:
| Element type | S | T | R | I | D | E |
|---|---|---|---|---|---|---|
| External entity | ✓ | ✓ | ||||
| Process | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Data store | ✓ | ✓ (logs) | ✓ | ✓ | ||
| Data flow | ✓ | ✓ | ✓ |
Spoofing, Tampering, Repudiation, Information disclosure, Denial of service and Elevation of privilege. Going through the upload feature element by element gives a list like this:
- Spoofing (browser). A stolen or forged session token uploads a photo for someone else. Mitigation: validate the token on every request, keep sessions short-lived, and tie the object key to the authenticated user id, never to a value from the request.
- Tampering (bucket to processor). A file named
photo.jpgis something else entirely. Mitigation: check the file's actual format, not its name or declared type, and re-encode every image before anyone else sees it. - Repudiation (API). A user denies uploading an offensive image, and nothing proves otherwise. Mitigation: log the user id, object key, time and client address for every upload.
- Information disclosure (bucket). The bucket allows public listing, or photos keep their GPS coordinates in EXIF metadata. Mitigation: a private bucket with short-lived signed URLs, and metadata stripped during re-encoding.
- Denial of service (API and processor). Huge files or images that decompress to enormous sizes exhaust memory. Mitigation: limits on file size and pixel count, and timeouts in the processor.
- Elevation of privilege (processor). A crafted file exploits a bug in the image library and runs code with the processor's permissions. Mitigation: run the processor in a sandbox with access to nothing but its bucket prefix and its one table.
Write the threats on the diagram as short numbered lines in a note next to the elements they affect, and link each one to the ticket that tracks the fix. The diagram then doubles as the summary of the review.
Rules for threat modeling diagrams
- Draw the feature, not the company. One DFD per feature or per service. A diagram of everything has no room for the details that matter.
- Show where authentication happens. Mark the process that checks identity on each boundary-crossing flow.
- Include the paths nobody demos. Admin tools, support access, batch jobs and backups cross boundaries too.
- Keep it at one level of detail. A context-level DFD shows the system as one process; a level 1 DFD breaks it into its main processes. Pick one per diagram.
- Version it with the feature. When the design changes, the threats change. Update the diagram in the same pull request as the design document.
Specialized tools or a shared canvas
Free tools such as OWASP Threat Dragon and the Microsoft Threat Modeling Tool are built for this job and can suggest threats for each element. They work well when a security team runs the process.
A shared canvas works better when the people who build the feature draw the diagram together during design: the DFD sits next to the architecture diagrams, everyone edits it live, and the notes stay attached to the elements. Either way, the conversation around the diagram is the valuable part.
Build it in Archboard
- Sign in with Google or GitHub and create a diagram.
- Add a Core Frame for each trust zone and name it after the zone, for example
Trust zone: app tier. - Add external entities as Core Box nodes, processes as Ellipse shapes from the Core pack, and data stores from the Data pack (Object Store, Postgres).
- Connect ports and label every edge with the data it carries.
- Add a Note next to the affected elements that lists each threat with its STRIDE letter, number and ticket.
The example uses 10 diagram nodes plus three notes listing seven threats, within the Free plan. For the network side of security, see the zero trust architecture diagram template, and for mapping personal data, the GDPR data mapping use case.
FAQ
Is a data flow diagram the same as an architecture diagram? No. An architecture diagram shows components and how they connect; a DFD shows how data moves and where trust changes. They often share boxes, but the DFD is drawn for the security question.
STRIDE or another method? STRIDE is a good default for software features. LINDDUN focuses on privacy threats, and PASTA is a risk-centric process for larger programs. The diagram is the same starting point for all of them.
Who should be in the room? The engineers who build the feature, someone who will operate it, and a security engineer if you have one. The people who know the code find the threats; the security engineer keeps the walk-through honest.
How long should it take? An hour for a feature like the photo upload is typical: 15 minutes to draw, 30 to walk STRIDE, 15 to agree on fixes and owners.
How often should we update the model? Whenever a flow crosses a new boundary, a new data store appears, or the feature changes who can do what.