ATALAIA
  1. Home
  2. Resources
  3. Blog
  4. Abuse cases belong next to user stories
Design · Guide

Abuse cases belong next to user stories

Write the misuse story in the same ticket as the feature, and security requirements stop being a document nobody opens.

4 min readAtalaia team

RequirementsAgileOWASP ASVS

Most teams have security requirements somewhere. They live in a wiki page, a policy PDF or a spreadsheet that was written once for an audit. Developers do not read them while building, because they are not where the work happens. The work happens in tickets.

The fix is simple and slightly boring: put the abuse case in the same ticket as the user story. If the story says what a legitimate user wants, the abuse case says what someone else wants from the same feature. Both get refined, estimated and tested together.

What an abuse case is

A user story has a familiar shape: as a customer, I want to export my invoices, so that I can send them to my accountant. An abuse case flips the actor and the goal: as another logged-in customer, I want to export someone else's invoices, so that I can read their billing data.

It is not a threat model. It is a single, concrete misuse of one feature, written in plain language, small enough to fit in the ticket description. The threat model is where you reason about the whole system; the abuse case is where that reasoning lands in front of the person writing the code.

Good abuse cases share three traits:

  • A named actor. Another tenant, an unauthenticated visitor, a support agent, a compromised integration. Not "a hacker".
  • A specific gain. Read data, change state, spend money, deny service, escalate a role.
  • A testable outcome. You can write the test that proves it does not work.

A template that fits in a ticket

Keep it short enough that nobody skips it. This is the block we suggest adding to your story template:

## Abuse cases
- As [actor], I want to [misuse], so that [gain].
  Expected: [what the system does instead]
  Test: [unit | integration | QA | manual]

## Security acceptance criteria
- [ ] Object-level access checked on every export request
- [ ] Export is rate-limited per account
- [ ] Export events are logged with actor and object id

The "Expected" line is the important one. It turns a worry into a requirement. "Someone could export other people's invoices" is a worry. "Requesting an invoice id that belongs to another account returns 404 and writes an audit event" is a requirement a developer can build and QA can test.

Where the abuse cases come from

You do not need a security engineer in every refinement session. You need a short list of prompts that the team runs through for each story. These cover most features:

  1. Whose data is this? If the story touches an object owned by a user or tenant, write the "other user" abuse case.
  2. Who can change it? If the story writes state, write the "lower role" abuse case.
  3. What does it cost us? If the story sends email, calls a paid API or generates files, write the "do it ten thousand times" case.
  4. What does it trust? If the story accepts a file, URL, webhook or free text, write the "hostile input" case.
  5. Who will deny it? If the story moves money or permissions, write the "it was not me" case, which usually means logging.

For the requirements themselves, OWASP ASVS is a good menu. Pick the controls that match the abuse cases you wrote, and link the ASVS item in the acceptance criteria. Copying the whole standard into your backlog helps nobody.

A worked example

Take a story for a team-invite feature: as an admin, I want to invite a colleague by email, so that they can join my workspace. Running the prompts gives:

PromptAbuse caseExpected
Whose dataA member of workspace A sends an invite into workspace BInvite endpoint checks the caller belongs to the target workspace
Who can change itA viewer invites someone as adminCallers cannot grant a role higher than their own
What does it costA script sends thousands of invites to arbitrary addressesPer-workspace and per-user rate limit; invites expire
What does it trustThe invite token is guessable or reusableSingle-use, random, time-limited token bound to the email

Four rows, perhaps ten minutes of conversation. Each row becomes an acceptance criterion and, ideally, an automated test. That is the whole method.

Making it stick

The method fails quietly when abuse cases become a box to tick. A few habits help:

  • Definition of ready. A story that touches data, roles or money is not ready without at least one abuse case.
  • Definition of done. The abuse case has a test, or an explicit note on why it is covered elsewhere.
  • Review the misses. When a pentest or bug report finds something, ask which story it belonged to and whether an abuse case would have caught it. Add the pattern to the shared page.
  • Feed the threat model. Abuse cases that keep repeating point at a design weakness. Take them back to the architecture and fix it once.

Think of it as the inspection sheet that travels with the part down the line, rather than a manual kept in the office.

What to do on Monday

  1. Add the abuse case block to your story template.
  2. Print the five prompts and use them in the next refinement session.
  3. Pick the three stories in the current sprint that touch user data and write their abuse cases now.
  4. Agree with QA that each abuse case gets a test, even a manual one.
  5. After a month, look at the shared page and see which patterns repeat. Those are your next design conversations.

Where this sits on the line

In the tower (in development):

Talk it through

A 30-minute call. No slides, no price list, and a next step either way.