Give every abuse case a short ID, put that ID in the test name and in a comment next to the control in code, and keep one table that lists them all. Gaps, such as an abuse case with no test, then show up in a review instead of an incident.
Why traceability helps
An abuse case on a wiki page protects nothing by itself. OWASP's Abuse Case Cheat Sheet recommends referencing abuse case IDs in design documents, code comments or annotations so you can see where each one is handled. It also lists unit, integration or functional security tests in CI as a way to validate them, and notes those tests catch accidental removal of protections later.
Traceability connects the three things: the risk, the control, the proof.
Step 1: ID scheme
Keep it boring. Use a prefix and a number, such as AC-014. Do not encode meaning in the number. Store IDs in the place the team already uses, a spreadsheet or a ticket label.
Step 2: Record each abuse case
For each one, keep these fields:
| Field | Example |
|---|---|
| ID | AC-014 |
| Feature | Discount codes |
| Scenario | Attacker redeems a single use code many times in parallel |
| Countermeasure | Atomic redemption check in the order service |
| Test | test_AC014_code_redeems_once |
| Status | Tested, manual only, or open |
| Owner | A named person or team |
The cheat sheet's workshop process uses a spreadsheet with tabs for features, abuse cases and countermeasures, so this table is a natural extension.
Step 3: Link in both directions
- In the test name or marker: include the ID so a search finds it.
- In the code: a short comment at the control, naming the ID and what it protects.
- In the ticket: link the abuse case when stories are written, since the cheat sheet suggests adding selected cases to stories as acceptance criteria or specifications as security requirements.
- In the pull request template: a line asking whether this change touches any abuse case controls.
Step 4: Check for gaps
Run a simple script or a manual review once per release:
- Every ID in the table appears in at least one test name or has a "manual only" status with a named checker.
- Every test that names an ID points to an ID that still exists.
- Every control comment names an ID that is still in the table.
Orphans in either direction mean something changed without anyone updating the record.
Keeping it lightweight
Do not create IDs for every conceivable attack. Cover the abuse cases the team agreed to address, as the cheat sheet's workshop does. Retire IDs when a feature is removed, and say so in the table rather than deleting the row, so history survives.
Keep the table next to the code if you can, for example in the repository, so changes go through review. A table in a document nobody opens will rot.
What auditors and buyers see
A table like this gives a concrete answer to questions about how security requirements are tested. It shows each requirement, the control, and the evidence. It does not claim a certification or an attestation, it simply shows your process, which is often what the questioner wants.
Try it yourself
Click through it at your own pace, or open it full screen. See where a pull request check can stop a change, and imagine a rule that fails when an abuse case has no test.
Safeguard's policies and gates, and its compliance and evidence automation, can record this kind of check. The free scan is a quick start for dependency findings.
Quick check
Do I need special software for this?
No. A table in the repository and a naming convention are enough to begin with.
What if an abuse case cannot be automated?
Mark it manual only, name who checks it and when, and keep the evidence of each check.
Sources
Last reviewed: 19 October 2026.