Feature-based threat modelling
A student portal adds a new upload feature. Students can submit homework, and teachers can leave feedback.
That sounds small enough to build. A form, a file input, a submit button, a page for the teacher.
It is also small enough to threat model properly.
Feature-based threat modelling takes one feature and walks it from start to finish. At each step, you ask what could go wrong and what the code needs to check.
Walk the feature
Start with the normal story:
- A student signs in.
- The student uploads a file.
- The server stores it.
- A teacher opens the submission.
- The teacher leaves feedback.
- The student reads the feedback.
That list is the map. You do not need a fancy diagram to start.
Now mark the places where a value crosses a trust boundary:
| Step | Value crossing the boundary | What to ask |
|---|---|---|
| Upload | Filename, file type, file size | Did the server check the file itself? |
| Store | Path and metadata | Can one student overwrite another file? |
| Teacher view | Submission id | Is this teacher assigned to this student? |
| Feedback | Feedback text | Can it become script when displayed? |
| Student view | Feedback id | Can one student read another student's feedback? |
The feature now has shape. You can see where security decisions belong.
Start with the story, then add the threats
If you start with threat names, the exercise feels abstract.
If you start with the feature story, each threat has somewhere to land.
Then mark the moments where your app receives something it did not choose. Those are the spots where the server needs to ask more questions.
Turn threats into checks
A feature model should not end as a list of worries.
For the upload feature, a worry might be:
A student could upload something unsafe.
That is true, but it is too vague to build from. Make it a check:
- Limit file size before storage.
- Allow only expected file types.
- Generate the stored filename on the server.
- Store files outside the public app directory.
- Check the teacher is assigned to the student before showing the file.
Now the model can become acceptance criteria.
A threat becomes useful when the next developer can turn it into code or a test.
"Unsafe upload" is a worry. "Limit file size and generate the stored filename on the server" is a check someone can build.
Try it on teacher feedback
Now use the same method yourself.
The feature says: teachers can leave feedback on student submissions.
Answer the five feature-based questions before reading on.
- Who sends the value?
- Who reads it later?
- What decision matters?
- What could go wrong?
- What should the code check?
Compare your answers
| Question | A reasonable answer |
|---|---|
| Who sends the value? | The teacher sends feedback text. |
| Who reads it later? | The student, and possibly another teacher. |
| What decision matters? | Only an assigned teacher can leave feedback. |
| What could go wrong? | Feedback could contain script, or land on the wrong submission. |
| What should the code check? | Assignment on the server, text length, and safe output when displayed. |
Question 2 is the one that carries the most weight and gets the least attention. Naming who reads a value later is what tells you it will be rendered into a page, which is what makes "could contain script" a question worth asking at all.
Answer only question 1 and you get input validation. Answer question 2 as well and you get output safety too.
The exact fix comes later in the handbook. The habit matters now: walk the feature, mark the boundary, write the check. That's the whole method.
The front end can guide, but the server decides
The page can hide feedback controls from teachers who are not assigned.
The route still has to check the assignment, because anyone can call the route directly.
Who may write it? Which submission does it belong to? Who may read it later? Security thinking is noticing those decisions before the code quietly answers them for you.
Where this goes next
Feature-based threat modelling is the day-to-day version of STRIDE. You can run it inside planning, write the checks into the ticket, and test them before the feature ships.
Next, OWASP and live bugs changes the timeline. Instead of asking what could go wrong before release, it gives names to the things that already went wrong in real apps.

