Course outline

Secure Software Development / Basic: outcomes, models, and decisions / Lesson 4

Design misuse cases without operational attacks

Challenge business assumptions with safe local scenarios and explicit protected invariants.

About 4 min readContent reviewed
On this page

Lesson goals

  • Distinguish an abuse scenario from a generic vulnerability label.
  • Build bounded negative cases and verify that legitimate use still works.

Describe an unwanted business outcome

An abuse case explains how a feature could be used to obtain an outcome the product should prevent. In the workshop service, one organizer might try to export another organizerโ€™s attendee contacts, or a registration change might bypass a capacity rule. Name the actor capability, intended action, violated invariant, and affected asset. A label such as injection or broken access control can help categorize the issue later, but it is not a complete scenario. The scenario should remain understandable to product and development reviewers without requiring exploit instructions or a live target.

Vary one capability at a time

Keep the attacker model bounded: an ordinary signed-in organizer can choose a workshop id but cannot set the trusted subject established by the application. A local test should change the requested resource while holding that subject constant. Do not invent unlimited administrative power unless the scenario explicitly studies that boundary. The first program models assignment checks with invented identifiers. It tests a policy difference rather than sending an unauthorized request. A real route must obtain both subject and resource scope through reviewed boundaries before this policy model can support an integration claim.

python A local resource-substitution policy model
assignments = {"organizer-a": {"workshop-1"}, "organizer-b": {"workshop-2"}}
def may_export(subject, workshop):
    return workshop in assignments.get(subject, set())

assert may_export("organizer-a", "workshop-1") is True
assert may_export("organizer-a", "workshop-2") is False
assert may_export("unknown", "workshop-1") is False
print("bounded resource-substitution cases checked")
Expected output
bounded resource-substitution cases checked

The complete program uses a fixed subject and synthetic resource ids to check allowed and denied relationships. It does not authenticate the subject, enumerate resources, contact a target, or prove that a real handler invokes the policy.

Check the business rule across state changes

A capacity invariant can fail through sequential operations even when every individual request looks ordinary. The fictional rule allows at most two active registrations in a tiny workshop. The second program accepts a seat while capacity remains and refuses the next addition without increasing the count. This is a sequential business model, not a concurrency mechanism. In an actual service, simultaneous reservations need an atomic enforcement design and controlled integration evidence. Do not use bursts of real requests to test this course example; the local model is enough to clarify the expected policy.

python A bounded fictional registration invariant
def reserve(active, capacity):
    if active >= capacity:
        return "FULL", active
    return "ACCEPTED", active + 1

status, count = reserve(1, 2)
assert (status, count) == ("ACCEPTED", 2)
status, count = reserve(count, 2)
assert (status, count) == ("FULL", 2)
print("capacity invariant preserved sequentially")
Expected output
capacity invariant preserved sequentially

This complete program checks one accepted and one refused local transition. The capacity of two is classroom data. It provides no evidence about concurrent commits, database locks, rate limiting, or real workshop availability.

Prioritize scenarios by product meaning

Choose scenarios that could cause meaningful disclosure, unauthorized state change, or loss of a critical workflow. Include alternate entry points such as exports, batch updates, and background actions where the same invariant applies. Avoid maximizing a count of dramatic-sounding cases with no link to the model. For each scenario, identify the preventive control and what observation would show it failed. A safe classroom case can use strings and in-memory state to explore the decision without collecting real data, probing accounts, generating load, or bypassing an actual control.

Keep allowed behavior in the same review

A defense that denies all exports prevents the abuse case while breaking the product. Pair each important negative with a legitimate positive and examine exact field and state expectations. After a repair, check adjacent conditions such as an organizer losing an assignment or a registration becoming cancelled. Keep a concise explanation of why the case matters and which assumptions it uses. The outcome is a defensible set of abuse-oriented requirements and regressions, not a claim that every possible adversarial behavior has been explored or that the deployed system is secure.

Common errors and fixes

An abuse case is only a vulnerability name

Why it happens
The unwanted outcome and actor capability are absent.
How to fix it
Write the asset, action, capability, and violated invariant.
Prevent it next time
Review scenarios with both product and implementation context.

The negative passes because everyone is blocked

Why it happens
Legitimate behavior is not represented.
How to fix it
Add an assigned-organizer success and exact allowed output.
Prevent it next time
Pair denial cases with positive cases.

A sequential capacity model is called race-safe

Why it happens
The test never exercises atomic concurrent enforcement.
How to fix it
State the local policy limit and assign atomicity verification separately.
Prevent it next time
Keep policy and mechanism claims distinct.

Check your understanding

1. Write a safe case for an organizer changing workshop-1 to workshop-2 in an export request.

Show worked solution

Keep the trusted subject organizer-a fixed, define assignment only to workshop-1, and require refusal plus no export artifact for workshop-2. Add the allowed workshop-1 case. Run only the local policy or an explicitly approved isolated component fixture; no real account or target is needed.

2. Why is a capacity case relevant even if the input schema is valid?

Show worked solution

The schema can accept an ordinary registration shape while the requested transition violates the current workshop capacity. Test the business invariant against controlled state and verify unchanged count on refusal. Representation validity and permitted state change are different properties.

Key takeaways

  • Abuse cases connect capabilities to unwanted product outcomes.
  • Negative scenarios need protected invariants and legitimate positives.
  • Local models clarify policy without operational attacks.

Official references