---
title: Threat modelling a payments flow in ninety minutes
url: "https://cs.abinantony.io/blog/threat-modelling-a-payments-flow"
category: Practice
published: 2025-12-15
updated: 2026-02-10
type: article
source: Abin Antony Security
---

# Threat modelling a payments flow in ninety minutes

> A ninety-minute payments threat model runs in four parts: draw the flow with trust boundaries (20 minutes), list abuse cases (20 minutes), apply STRIDE per boundary crossing (35 minutes), and convert the top risks into backlog tickets with acceptance criteria (15 minutes). Three people is the right number.

Threat modelling has a reputation problem: it sounds like a methodology, which sounds like two days and a facilitator. So teams skip it, ship the payment flow, and discover in an assessment that the amount is trusted from the client.

Here is the version that actually happens: ninety minutes, three people, one flow — the one that moves money.

## Who is in the room

- One engineer who knows how the flow is implemented.
- One person who knows the business rules — refunds, partial payments, promotions, what "paid" means.
- Someone to write it down who is not either of them.

More than four people and it becomes a meeting. Fewer than three and you miss the gap between what the code does and what the business assumes.

## Minutes 0–20: draw it

On a whiteboard, in the room, live. Not a diagram from the wiki, which reflects the architecture of eighteen months ago.

- Every component that touches the transaction: app, API, payment gateway, webhook receiver, database, queue, ledger, email.
- Every arrow, labelled with what data crosses it.
- Draw the trust boundaries as lines: client to server, your infrastructure to the gateway, gateway callback back to you.
- Mark where the authoritative record of "this order is paid" lives. Arguments start here, and the argument is the point.

## Minutes 20–40: abuse cases

Stop asking what could break. Ask what someone would try if they wanted free goods, and write each as a sentence.

- "I change the amount in the request and pay ₹1 for a ₹10,000 order."
- "I replay the gateway’s success callback for an order I cancelled."
- "I start a payment, close the app before the callback, and claim the order never completed."
- "I apply the same single-use coupon in twenty parallel requests."
- "I refund to a different account than the one that paid."
- "I am an insider issuing a refund to myself, and nothing records that I did."

> Every one of these has shown up in a real assessment. The parallel-coupon one is the most consistently profitable, because inventory and promotion code is written as if requests arrive politely, one at a time.

## Minutes 40–75: STRIDE at each boundary

Walk each boundary crossing and ask the six questions. Speed matters more than completeness — you are looking for the ones that make the room go quiet.

| Threat | Question for this flow | Typical control |
| --- | --- | --- |
| Spoofing | Can someone pay as another user? | Authenticated session bound to the order owner |
| Tampering | Can the amount, currency or item be changed? | Server computes the amount; client sends only an order reference |
| Repudiation | Can a user deny a transaction we cannot prove? | Immutable audit log with gateway references |
| Information disclosure | Does the response leak other orders or card data? | Response shaped per endpoint; no card data stored |
| Denial of service | Can payment attempts be used to exhaust something? | Rate limits per account and per instrument |
| Elevation of privilege | Can a customer trigger a refund or adjust a ledger? | Refunds behind a separate role with dual control above a threshold |

Repeat for the webhook boundary. That one earns its own pass, because callbacks are unauthenticated by default in more integrations than anyone expects: verify the signature, verify the amount against your own record, and make processing idempotent on the gateway’s reference.

## Minutes 75–90: turn it into tickets

The output is not a document. It is between four and eight backlog tickets, each with an acceptance criterion a reviewer can check.

1. "Server derives the payable amount from the order; the API ignores any client-supplied amount. Test: a tampered amount returns 400."
2. "Webhook handler verifies the signature and is idempotent on the gateway reference. Test: replaying a callback creates no second fulfilment."
3. "Coupon redemption is atomic under concurrency. Test: twenty parallel redemptions of a single-use coupon succeed once."
4. "Refunds are role-restricted and audit-logged with actor, amount and reason. Test: a customer role receives 403."

Photograph the whiteboard, attach it to the epic, and put a recurring ninety-minute session in the calendar for the next quarter. A threat model that is refreshed twice is worth more than one that was perfect once.


---

Abin Antony Security — Abin Antony, Kochi, Kerala. Contact: abina35@gmail.com · https://cs.abinantony.io
