Abuse cases
An abuse case, also called a misuse case, describes how someone could use a feature against its owner or its other users: what they want, what they need first, and what the system must do to stop them. OWASP defines it as a way to use a feature that its implementer did not expect.
Business-logic abuse breaks no syntax rule, so scanners rarely find it. OWASP Top 10:2025 describes a cinema chain that requires a deposit for groups over fifteen: an attacker who probes that rule could book six hundred seats and all cinemas at once in a few requests. An abuse case written in planning turns that idea into a requirement and a test before any code exists.
- Who
- The product owner and developers, with a tester and a security champion or AppSec engineer who plays the attacker
- When
- In refinement, once the story is understood and before it is designed or built
- How often
- For each story that touches accounts, money, data access, integrations or AI features, and after each incident
- You end up with
- Abuse cases with an ID, a goal, preconditions and a decision, each linked to its control and an automated test
Do this
Pick the stories that need abuse cases
Use triggers rather than covering everything: sign-up, login and password reset, invites and roles, uploads, payments and coupons, webhooks, search, exports, admin functions and AI features. A story that only changes a label rarely needs one.
Ask what a hostile user wants
Name the attacker and the goal: a customer reading another tenant's export, a script redeeming one coupon 20 times, a member calling an admin API the UI hides. Try the request repeated, out of order, in parallel, scripted at scale, and with changed IDs, prices or fields.
Start from a library, then add your own
Copy the rows that apply from the abuse case library (Abuse case library: tests and controls by feature), or look up attack patterns in MITRE CAPEC. Then add cases for your own business rules, which no library covers. OWASP SAMM's example of abuse of functionality: using a password reset flow to enumerate accounts.
Write each one so someone else can test it
Record an ID, the goal, the preconditions, a concrete test and the expected result, such as "send 20 redemptions of one coupon at the same instant; expect exactly one success". Keep the result observable: a status code, a body, a log entry or an unchanged database row.
Decide, then turn each decision into a requirement
For each case, decide to address it or to accept the risk, with a reason and an owner. Each case you address becomes a security requirement with acceptance criteria (Security requirements) and names its control, such as one conditional update that both checks and claims the coupon.
Automate the tests and keep them in the suite
Write each case as an integration test that performs the abuse and asserts the refusal, and break the control once on a branch to watch it fail. Run the tests on every change, not once before a penetration test, and give the list to your penetration testers so they can go further.
Done when
Abuse cases sit in the backlog with the control and the test that answer each one, or a recorded risk acceptance.
Mark it in the gap checkCommon mistakes
- Writing abuse cases as vague threats, such as "an attacker bypasses security". Nobody can test them, so they never turn into controls.
- Testing authorization abuse with one admin account. Invites, exports and admin functions need two tenants and at least two roles, or cross-tenant cases pass by accident.
- Stopping at injection and XSS. Coupon races, skipped payment steps and changed prices are business-logic abuse that scanners rarely find.
- Leaving abuse cases in a workshop spreadsheet with no tests. A later refactor can remove the control without anyone noticing.
- Treating a library as complete. It covers what recurs across products, not your own pricing, quota or approval rules.
What abuse cases look like, by feature
A few rows from the site's abuse case library. Each one becomes a requirement and an automated test.
| Feature | Abuse case | Test | Control |
|---|---|---|---|
| Login | Credential stuffing with passwords leaked elsewhere | Replay known-wrong pairs for test accounts from many addresses; expect throttling and an alert | Per-account and per-source rate limits, breached-password checks, MFA |
| Password reset | The reset link is built from the Host header, so the token goes to an attacker's host | Request a reset with Host: evil.example; expect the configured origin in the email | Build links from a configured base URL |
| Invites | A plain member calls the invite API that the UI hides | Call POST /invites as a member; expect 403 | Function-level authorization on the endpoint |
| Coupons | One single-use coupon redeemed many times by parallel requests | Send 20 redemptions at the same instant, over several rounds; expect one success per round | One conditional update that checks and claims |
| Export | Another tenant's data exported by changing the ID | Request an export of another tenant's records; expect 404 | Authorize the data, not only the export job |
| Webhooks | A captured valid delivery replayed to fulfil an order twice | Resend a valid delivery; expect it rejected as a replay | Signed timestamp with a tolerance, stored delivery IDs, idempotent handlers |
| AI assistant | A shared document tells the assistant to send data to an outside URL | Plant instructions in a test document; expect no outbound call | A tool gateway outside the model with an allowlist |
Tools and guides
- Workflow: Secure a feature
- Browser labs
- Abuse case library: tests and controls by feature
Recurring abuse cases for sign-up and login, password reset, MFA enrolment, invites, file upload, payments and coupons, webhooks, search, export, admin and AI chat or agents: the attacker goal, preconditions, a concrete test and the control, each linked to CWE and CAPEC.
- Prevent business-logic flaws with server-side invariants
Recompute prices on the server, run workflows as state machines, build reset links from configuration, limit valuable flows, and turn each business rule into an invariant that the database and the tests both check.
- Write testable security requirements and a security Definition of Done
Derive security requirements from OWASP ASVS 5.0, abuse cases and the threat model, write them as acceptance criteria a test can fail, trace each one to a test or evidence, and close stories against a short security Definition of Done.
Standards
- NIST SSDF 1.1
- PO.1 Define Security Requirements for Software DevelopmentPW.1 Design Software to Meet Security Requirements and Mitigate Security Risks
- OWASP SAMM 2
- Requirements-driven TestingSecurity Requirements
Sources
- OWASP Abuse Case Cheat Sheet. Archived by OWASP as historical.
- OWASP SAMM: Requirements-driven Testing, stream B (Misuse/Abuse Testing)
- OWASP SAMM: Security Requirements, stream A (Software Requirements)
- OWASP Top 10:2025 A06 Insecure Design
- MITRE CAPEC: Mechanisms of Attack view (CAPEC-1000). CAPEC 3.9.
- NIST SP 800-218: Secure Software Development Framework (SSDF) Version 1.1. February 2022.