Abuse Cases and Misuse Cases: Threat Modeling at the User Story Level

Every user story describes what a feature should let someone do. Almost none of them describe what it shouldn't. "As a customer, I want to share an invoice by link" says nothing about who else might open that link, how long it works, or what happens when it's forwarded. Those questions get answered by accident, usually by whoever writes the code, and usually by not thinking about them at all.

An abuse case fixes that by writing the story the attacker would write. It's the smallest unit of threat modeling there is: one feature, one adversary, one harmful goal, written in the same backlog and refined in the same meeting as the story it threatens. This guide covers what abuse cases and misuse cases are, a template that works, worked examples, and how to turn each one into acceptance criteria and a scored threat.

In short: for each story that touches identity, permissions, money, personal data, files or the internet, ask "how could someone use this to cause harm?" Write the answer as a story from the attacker's point of view, then turn it into acceptance criteria the feature must meet before it's done. If the threat is too big for one story, it goes into your risk register with a score and an owner.

What is an abuse case?

An abuse case describes an interaction with a system that harms the system, its owner or its users. The idea was introduced by John McDermott and Chris Fox in 1999 as a way to bring security into use-case based requirements: alongside the use cases a system should support, you write down the ones it must resist.

In an agile backlog, the same idea usually appears as an abuser story or evil user story, mirroring the familiar user story format:

User story: As a customer, I want to share an invoice by link, so that my client can view it without an account.

Abuse case: As someone who was never sent the link, I want to guess or find invoice links, so that I can read other businesses' invoices and their clients' details.

The second sentence is uncomfortable to read, and that's the point. It names an actor, a method and a harm, which is everything you need to decide what the feature must do to resist it.

Abuse cases vs misuse cases

You'll see both terms, often used interchangeably. The distinction, where people make one, comes from where they were introduced:

Abuse caseMisuse case
OriginMcDermott and Fox, 1999Sindre and Opdahl, early 2000s
ShapeA harmful interaction described on its ownA use case for a hostile actor, drawn on the same diagram as the normal use cases it "threatens"
Typical home todayAgile backlogs, as abuser or evil user storiesRequirements documents and UML use-case diagrams
Common informal meaningDeliberate harm by an attackerHarm from using a feature the wrong way, deliberately or by mistake

For practical purposes, pick one term and use it consistently. What matters more is that you cover both deliberate attackers and honest mistakes. A customer who pastes an invoice link into a public forum isn't malicious, but the result is the same disclosure.

A template that works

An abuse case needs five parts. Anything less and it's too vague to act on.

  1. Actor. Who is doing this? Be specific: an anonymous internet user, a logged-in customer of another tenant, a former employee, a support agent, a compromised partner. Our post on threat actors covers the usual cast.
  2. Goal. What harm do they want? Read data, change data, take money, deny service, gain access they shouldn't have.
  3. Method. How would they use this feature to do it? Abuse cases are tied to the story; "hack the server" is not an abuse case.
  4. Impact. What happens if they succeed, and to whom?
  5. Acceptance criteria. What must be true of the feature for the abuse case to fail? This is the part that gets built and tested.

Written out, that's: As [actor], I want to [method], so that [goal]. If this succeeds, [impact]. The feature is done only when [acceptance criteria].

How to find abuse cases for a story

Staring at a story and asking "what could go wrong?" works for experienced people and stalls everyone else. A few prompts make it reliable:

  • Run the story through STRIDE. Could someone pretend to be another user here (spoofing), change something they shouldn't (tampering), deny doing it (repudiation), see something they shouldn't (information disclosure), make it slow or expensive (denial of service), or get more access than intended (elevation of privilege)? Six quick questions usually produce one or two real cases.
  • Change the actor. Re-read the story as an anonymous user, a user from another tenant, a user with a lower role, an admin, and an automated script. Most authorisation bugs live in the gap between "as a customer" and "as a different customer".
  • Change the inputs. What if the ID belongs to someone else, the amount is negative, the file is 4 GB, the name contains a script tag, or the request is sent ten thousand times?
  • Follow the data. Where does it go after this feature? An email, a PDF, a log, an analytics tool, a third-party API? Each destination is somewhere it can leak.
  • Think about honest mistakes. Wrong recipient, wrong tenant selected, a link forwarded, a bulk action applied to everything. Misuse by accident causes as many incidents as abuse on purpose.

For more prompts, our threat modeling checklist has 29 STRIDE questions you can apply to a single story as easily as to a whole system.

Worked examples

These use Invoicely, the fictional invoicing app from our complete threat model example. Each starts from an ordinary story the team would write anyway.

1. Sharing an invoice by link

Story: As a customer, I want to share an invoice by link, so that my client can view it without an account.

Abuse case: As someone who was never sent the link, I want to guess, find or receive a forwarded link, so that I can read the invoice and the client's details. If this succeeds, a third party's name, address and billing details are disclosed, which may be a reportable personal data breach.

Acceptance criteria:

  • Links contain an unguessable random token (at least 128 bits), not a sequential invoice ID.
  • Links expire after 30 days by default, and the invoice owner can revoke them at any time.
  • Every view of a shared link is logged with time and IP address, and visible to the owner.

2. Inviting a teammate

Story: As an account admin, I want to invite a teammate by email, so that they can manage invoices with me.

Abuse case: As a member with the "viewer" role, I want to send an invitation request with the role set to "owner", so that I can take over the account. If this succeeds, a low-privilege user gains full control, including billing and deletion.

Acceptance criteria:

  • The server checks that the inviter's own role is at least the role being granted, on every request, regardless of what the UI shows.
  • Invitations are single-use, expire after 7 days, and are bound to the invited email address.
  • Role changes and invitations appear in the account's audit log.

3. Uploading a company logo

Story: As a customer, I want to upload my company logo, so that it appears on my invoices.

Abuse cases: As an attacker, I want to upload an SVG containing a script, so that it runs in the browser of anyone who views the invoice. Or: I want to upload a 2 GB file, or thousands of files, so that storage costs rise and invoice rendering stalls.

Acceptance criteria:

  • Only PNG and JPEG are accepted, checked by file content rather than extension, and the image is re-encoded on upload.
  • Uploads are limited to 2 MB, and each account keeps only its current logo.
  • Logos are served from a separate domain with a content type that can't execute script.

4. Exporting all invoices

Story: As an account owner, I want to export all invoices as CSV, so that I can send them to my accountant.

Misuse case: As a support agent impersonating a customer to debug an issue, I trigger the export and the file goes to my own inbox, or a departing employee exports the full client list on their last day. If this happens, the business's entire customer list leaves the system without anyone noticing.

Acceptance criteria:

  • Exports are only available to the owner role, and are blocked during support impersonation.
  • The export file is delivered to the requester's verified email address only, and the account owner is notified.
  • Exports are logged, and an unusual number of them raises an alert.

Notice that none of the acceptance criteria are "be secure". Each one is specific enough to build, to test, and to show an auditor. Our guide to writing mitigations auditors accept goes into the wording.

From abuse case to threat model

Most abuse cases are fully handled inside the story: the acceptance criteria get built, the tests pass, and the story is done. That's the ideal outcome, and it's why abuse cases are such a good fit for shift-left security: the fix ships in the same sprint as the feature.

Some abuse cases don't fit in a story, and those need to leave the backlog:

  • The fix is bigger than the feature. "Links must be revocable" might need a new token service. That's a design decision, not a line in a story.
  • The team decides not to fix it now. Accepting a risk is legitimate, but only if someone with authority accepts it on the record, with a date to revisit it.
  • It's part of a bigger attack. Example 2 is one step towards "take over a customer account". Other steps, such as credential stuffing or a stolen session, live in other stories. An attack tree puts them together so you can see which defence breaks the most paths.

For those, write the abuse case as a threat statement, score it on likelihood and impact, and put it in the risk register with a treatment decision and an owner. Our post on moving from threat model to risk register walks through it.

Where abuse cases fall short

Abuse cases are excellent at finding threats in what's being built. They're poor at finding threats in what already exists, or in how the pieces fit together, because no story ever describes those parts.

  • System-level threats stay invisible. In the Invoicely example, the most serious finding was that the admin console and the customer API share a database role. No user story would have surfaced that; drawing the data flow diagram did.
  • They depend on who's in the room. A team that has never seen an SSRF or a webhook forgery won't write an abuse case for one. Checklists and frameworks fill the gap.
  • They can become a ritual. "As a hacker, I want to hack the system" in every story is worse than nothing, because it looks like coverage.
  • Infrastructure and supply chain fall outside stories. Your CI/CD pipeline, cloud permissions and dependencies need their own review.

The combination that works is abuse cases on every security-relevant story, plus a whole-system review with a diagram when the architecture changes. Our list of when to re-threat-model covers the triggers.

Making it part of refinement

  • Add one question to your definition of ready: "Does this story touch identity, permissions, money, personal data, files or an external interface? If so, does it have at least one abuse case?"
  • Timebox it. Five minutes per relevant story during refinement is enough. If it takes longer, the story probably needs a proper threat modeling session.
  • Let testers own the acceptance criteria. Testers are often the best abuse case writers on a team, because breaking things on purpose is already their job.
  • Reuse what you find. The same abuse cases come back for every file upload, invite flow and export. Keep a short library of them for your product and copy them into new stories.
  • Review them after incidents. If something went wrong that no abuse case predicted, write the one that would have.

Frequently asked questions

What is the difference between an abuse case and a misuse case?

In everyday use the terms are interchangeable: both describe how a feature could be used to cause harm. Strictly, misuse cases come from use-case modeling and are drawn alongside the normal use cases they threaten, while abuse cases describe harmful interactions on their own. Some teams also use "misuse" for accidental harm and "abuse" for deliberate harm. Pick one term and use it consistently.

Do abuse cases replace threat modeling?

No. Abuse cases are threat modeling at the size of a single user story. They catch threats in features as they are built, but they miss threats that only appear when you look at the whole system, such as a shared database role or an unprotected internal service. Pair them with a periodic data flow diagram review of the system.

Who should write abuse cases?

The team that writes the story: the product owner, the developers and the tester, during refinement. A security specialist can help when one is available, but the team knows the feature best, and five minutes of asking how it could be abused is enough to find the obvious cases.

How many abuse cases should a user story have?

Usually one to three, and none for stories that change nothing security-relevant. Prioritise stories that touch authentication, permissions, money, personal data, file handling or anything exposed to the internet.

Want to see the whole-system side? The complete threat model example takes the same Invoicely app from scope to risk register. No security team to lean on? Read building a security culture without a dedicated team.

Keep the abuse cases that outgrow a story

In ThreatTree you can model the bigger ones as attack trees, with each step tagged by its STRIDE category and scored on likelihood and impact. Every scored threat lands in a risk register with a treatment plan and an owner, next to the data flow diagram of the system it belongs to.

Get started free

Not ready to sign up? Get new threat-modeling guides by email instead.