Rules that work but can be gamed
Watch it happen
Mallory changes the price on an order form to one cent. The teller’s checklist passes and a pattern-checking scanner finds nothing wrong, so she gets a Gold account for a cent.
Mallory walks in to buy a Gold account. Customers fill in an order form, and the app puts the price in a price box.
Mallory says: One Gold account, please.In bank terms and app terms
| In the bank | In your app |
|---|---|
Are you exposed?
Your checkout or API takes price, amount, role, plan or discount from the request and uses it directly. Important steps (payment before access, email verified before upgrade) can be skipped by calling the next URL directly. Amounts, quantities or transfers are not checked for negative, zero or absurdly large values.
Look up prices, plans, roles and limits on the server, and treat everything in the request as a suggestion. Enforce the order of steps on the server: keep a status (pending, paid, shipped) and allow only valid moves, such as granting access only after payment is confirmed. Validate amounts (no negative, zero or absurdly large values), block self-transfers and reused coupons, and have an AI or a teammate review money flows.
What it looks like in code
Business logic fixes are app-specific, but common patterns:
// FIX: Price manipulation — look up price server-side
const PLAN_PRICES = { starter: 9, pro: 29, enterprise: 99 }
const amount = Object.hasOwn(PLAN_PRICES, plan) ? PLAN_PRICES[plan] : undefined
if (amount === undefined) return error("Invalid plan")
// FIX: Race condition — use atomic database operations
await db.query(
`UPDATE credits SET balance = balance - $1
WHERE user_id = $2 AND balance >= $1 RETURNING balance`,
[amount, userId]
)
// FIX: Missing ownership — always filter by authenticated user
const task = await db.query(
`SELECT * FROM tasks WHERE id = $1 AND user_id = $2`, [taskId, userId]
)
Ask your AI tool to fix it
Paste this into Cursor, Claude, Lovable, Bolt or whatever you build with.
Review every checkout, payment, transfer, coupon, subscription and role-change endpoint for business logic flaws. Never trust price, amount, plan, role or discount from the client; look them up on the server. Reject negative or zero amounts, enforce step order (payment confirmed before access), and block self-referrals and reused coupons. Also check Supabase RLS policies and Firebase rules for wrong-column mistakes like auth.uid() = id. Report each flaw and the fix.Where this comes from
The facts, figures and fixes on this page were checked against these sources on 25 Oct 2026. They are linked so you can check for yourself.
- Business logic vulnerabilityOWASPlogic flaws let attackers abuse intended functionality, can be devastating
- Business logic vulnerabilitiesPortSwiggerlogic flaws come from flawed assumptions and are invisible to people not looking
- A04:2021 Insecure DesignOWASPdesign-level flaws need threat modelling and review, not only patching
- API6:2023 Unrestricted Access to Sensitive Business FlowsOWASPabuse of purchase, coupon and referral flows
- Row Level SecuritySupabaseRLS policies compare auth.uid() to the right column
Spot a mistake or something out of date? Report a correction · How these guides are made and checked
The free, open-source scanner checks for most of the problems in these guides.