Platform

Platform overview How it works Authorization testing Evidence & reports Private scanning Integrations

Solutions

Security agencies Product teams Regulated industries Partner programme

Learn

Blog Knowledge hub Compare

Resources

Pricing Documentation Help centre FAQ Security & data What we haven’t proved

Company

About Contact Careers Sign in to the platform Start a $199 pilot →

Home / Blog / Business logic testing checklist

Playbooks

Business logic testing checklist: prices, coupons, workflows and race conditions

A practical business logic testing checklist for web apps and APIs: the rule to confirm, how to try to break it, and the fix that holds.

Cyberlop Labs · Updated · 15 min read

Illustration for Business logic testing checklist: prices, coupons, workflows and race conditions
Quick answer

A business logic testing checklist is a list of checks that try to break your application's own rules: prices, coupons, quantities, limits, workflow order and parallel requests. Write each rule as an invariant, test it with real accounts on staging, prove the result, fix it on the server and replay the exact exploit.

Key takeaways
  • Write down your invariants first: a rule you cannot state is a rule you cannot test.
  • The server must decide prices, totals, eligibility and workflow state; the client only suggests.
  • Scanners miss logic flaws because the traffic is valid, so test with real accounts and real flows.
  • Race conditions need parallel requests, repeated runs and a reconciliation of the final totals.
  • Turn every fixed flaw into an automated regression test, and prove the fix by replaying the exact exploit.

A business logic testing checklist is a written list of the rules your product depends on, each paired with a way to break that rule using only features the app already offers. Work through prices, quantities, coupons, workflow order, limits, timing and parallel requests, and confirm the server enforces each rule itself. Scanners rarely find these flaws because nothing looks malformed.

The list suits engineering and product teams, not only testers. Use it before a launch, to brief a pentester, or after a release that touched payments, onboarding or approvals. Each section gives the rule to confirm, test ideas you can run on a staging copy today, and the fix that usually holds. It follows the OWASP Web Security Testing Guide business logic chapter and adds the cases product teams meet in payments and promotions.

What is business logic testing, and why is it different?

A business logic flaw is a case where the application does exactly what the code says, but the code does not say what the business meant. OWASP's test is practical: if spotting the flaw takes knowledge of the business, you are probably looking at a logic problem. The request is valid, the user is signed in, and the response is a clean 200. The damage is a refund paid twice, a free upgrade, or stock that nobody paid for.

Injection flaws break the parser. Logic flaws break a promise, so the standards file them elsewhere: MITRE groups them under CWE-840, Business Logic Errors, a category whose members include unverified ownership, missing limits, single-use actions and workflow enforcement. MITRE marks the category itself as prohibited for mapping real vulnerabilities, so a finding should map to a member such as CWE-841 or CWE-770. OWASP places the wider theme under A06:2025 Insecure Design.

The root cause is often something you already know by another name: weak server-side authorisation, missing input validation, or no rate limiting. Testing for logic flaws is mostly testing whether those controls exist at the exact point where money, data or state changes.

Can scanners find business logic flaws?

An automated scanner sends payloads and watches for signs: an error message, a reflected script, a delayed response. A logic flaw gives none of those signs. Changing a quantity from 1 to -1 returns a normal page. Whether that page is a bug depends on a rule the scanner has never been told.

A tool needs to know the rule, reach the state where it applies (a paid order, a trial account) and recognise a wrong outcome. Most manage the second at best. A person, or a system that reads your code and your flows, supplies the rest.

The OWASP Web Security Testing Guide makes the same point: tools struggle with context, so people have to run these tests. A clean scanner report therefore tells you little about logic risk. Our post exploited, not suspected shows how we separate proven findings from guesses, and why your scanner has one login covers the related blind spot of testing from a single account.

Why do business logic flaws matter in 2026?

Because more attacks now start inside the application itself. The 2026 Verizon Data Breach Investigations Report found that 31% of breaches began with a software vulnerability, ahead of stolen passwords. Not all of those are logic flaws, but a logic flaw needs no malware and no stolen credential: only a valid account.

OWASP's 2025 list points the same way. A06:2025 Insecure Design maps 39 CWEs and 729,882 occurrences, with a maximum incidence rate of 22.18% and an average of 1.86%. A01:2025 Broken Access Control, the neighbour that logic flaws often overlap with, reports that 100% of the applications tested had some form of it. Getting it wrong is expensive: IBM's Cost of a Data Breach Report 2026 gives a global average of 4.99 million US dollars, a 12% rise on the year before.

Stat cards: 31% of breaches start with software vulnerabilities; 100% of tested apps had broken access control; IBM breach costs up 12%.
Figures from the 2026 Verizon DBIR, OWASP Top 10:2025 and IBM's 2026 breach cost report. Source: Verizon: 2026 Data Breach Investigations Report.
Bar chart: A01 Broken Access Control 3.74% average incidence; A06 Insecure Design 1.86% average incidence, OWASP 2025.
Average incidence rate across contributed data: Broken Access Control against Insecure Design. Source: OWASP: Top 10:2025, A01 Broken Access Control.

How do you prepare: flows, rules and invariants?

You cannot test a rule nobody wrote down. Spend an hour before you start and produce three short lists. This is the same discipline as a threat model, kept deliberately small.

  1. Flows that move money or value. Checkout, subscription change, refund, wallet top-up, payout, credit grant, referral reward, gift card, invoice approval.
  2. Flows that change state. Order status, KYC status, account activation, document approval, password reset, trial to paid, cancellation.
  3. Invariants. Statements that must always hold. For example: an order total equals the sum of server-side prices; stock never goes below zero; a coupon is used once per customer; a refund never exceeds the amount paid; only the approver can approve.

Each invariant becomes one or more test cases. Write them as sentences a product manager would agree with. If the team cannot agree on one, you have found your first design problem.

You also need accounts: two ordinary accounts in one tenant, one in another tenant, one with elevated rights and one brand-new account. Many logic flaws only appear when a second account touches the first one's object.

The business logic testing checklist at a glance

The table below is the short version. The sections after it explain each row with test ideas and fixes. Tick a row only when you have tried to break the rule and the server refused.

AreaRule to confirmQuick testUsual fix
Prices and totalsServer decides every price and totalEdit price, total or currency in the requestRecalculate from the catalogue on the server
QuantitiesQuantity is a positive whole number within stockSend 0, -1, 0.5, a huge numberStrict type, range and stock checks
Coupons and creditsEach code is valid, eligible and used as allowedReuse, share, expire, apply to wrong itemsRecord redemptions, check eligibility server-side
Workflow orderSteps happen in order and only onceCall step 3 without step 2; repeat step 3Explicit state machine on the server
LimitsSensitive actions have usage limitsRepeat the action past the stated limitPer-account limits with a stored counter
Race conditionsParallel requests cannot beat a checkSend the same request many times at onceAtomic updates, unique constraints, locks
Timing and expiryTime-based rules use server timeUse expired tokens, offers and trialsCheck expiry at the moment of use
Ownership and rolesOnly the right account can act on an objectUse account A's object ID from account BOwnership check on every action
Files and paymentsUploads and payment results are verifiedWrong file type; fake payment callbackVerify content and signed provider events

How the checklist maps to OWASP WSTG v4.2 and CWE

Use this table to show an auditor or a client which public test each row covers. WSTG v4.2 numbers its business logic tests 4.10.1 to 4.10.9.

Checklist areaWSTG v4.2 testClosest CWE
Prices, quantities, coupons4.10.1 Business Logic Data Validation; 4.10.2 Ability to Forge RequestsCWE-639, CWE-837
Hidden fields and signed values4.10.3 Integrity ChecksCWE-841
Timing and expiry4.10.4 Process TimingCWE-362
Limits and abuse4.10.5 Number of Times a Function Can Be Used; 4.10.7 Defenses Against Application MisuseCWE-770, CWE-837
Workflow order4.10.6 Circumvention of Work FlowsCWE-841
Files4.10.8 Unexpected File Types; 4.10.9 Malicious FilesCovered in file upload guidance

Prices, totals and currency

The rule: the browser or app may display a price, but only the server may decide it. Any value the client sends that influences money is a candidate for tampering, which is the idea behind price manipulation and parameter tampering.

Test ideas

  • Intercept the checkout request and change the unit price, line total, order total, shipping cost, tax amount or currency. Does the order complete at the edited value?
  • Change the product ID after the price has been fetched. Some carts price the item at add time and let the ID change later.
  • Add hidden fields to the request, such as a discount amount or a role or plan field, and see whether the server accepts them. This is the pattern behind mass assignment.
  • Check rounding. Split a total across many small lines and see whether rounding in your favour accumulates, a known pattern called rounding abuse.

What a good fix looks like

Never accept prices, totals or discount values from the client. Accept only identifiers and quantities, then compute everything from your own catalogue at the time of payment. Compare the amount the payment provider reports with the amount you expected, and refuse to fulfil if they differ. Use integer minor units (paise, fils, cents) for money, not floating point numbers.

Quantities and numeric limits

The rule: every number has a valid range, and the server enforces it. The classic failures are the negative quantity that turns a purchase into a credit, and the oversize number that wraps around or exceeds stock.

Test ideas

  • Send quantity values of 0, -1, 1.5, 1e9, a very long number, an empty string and the text "null".
  • Transfer or withdraw a negative amount. A negative transfer from A to B can quietly become a transfer from B to A.

What a good fix looks like

Validate type and range on the server for each numeric field, not only in the form. Reject, do not clamp, values you did not expect, and log the rejection. Check stock inside the same database transaction that reduces it, so two buyers cannot both succeed on the last unit.

Coupons, credits and referral rewards

The rule: a code can only be redeemed by an eligible account, on eligible items, within its limits, and the redemption is recorded exactly once. Promotions are where product rules are most numerous and least tested. The relevant patterns are coupon abuse, referral fraud, trial abuse, loyalty points abuse and gift card fraud. For a worked example of how discount rules collide, see the teardown in exploited, not suspected; this checklist covers the surrounding cases.

Test ideas

Single-use codes and credits

  • Redeem a single-use code twice, once after the other and once in parallel.
  • Apply the code, then change the cart to ineligible items before paying. Is eligibility checked again at payment?
  • Create several accounts with plus-addressed emails (name+1@example.com) and see whether each earns a signup or referral reward.
  • Start a trial again with the same email, phone number, card or device and see what your controls actually key on.

What a good fix looks like

Store each redemption as a row tied to the account and the order, with a unique constraint where the rule says once. Recheck eligibility at the final step, not only when the code is entered. Pay referral rewards only after a real, non-refundable event, and reverse them when the underlying order is reversed. Decide, in writing, what counts as the same customer.

Workflow order and state transitions

The rule: each object moves through a fixed set of states, and the server rejects any move that is not allowed. OWASP calls this circumvention of work flows, and MITRE lists CWE-841, Improper Enforcement of Behavioral Workflow among the members of CWE-840. In code it is a state machine that exists only in the front end.

Test ideas

  • Skip steps. Call the "confirm order" endpoint without paying, the "activate account" endpoint without verifying the email, or the "ship" endpoint on an order that is still pending. This is workflow bypass.
  • Repeat a step. Submit the final step twice. Does fulfilment happen twice?
  • For approvals, confirm that the requester cannot approve their own request and that approval by one role does not satisfy a second-approver rule (separation of duties).

What a good fix looks like

Model the states and allowed transitions in one place on the server. Every endpoint that changes state must name the state it expects and refuse otherwise. Store who did what and when. Make the final step idempotent, so repeating it with the same key returns the first result instead of repeating the work.

Usage limits and abuse of sensitive flows

The rule: any action that costs money or reputation when repeated has a limit that the server counts. OWASP lists this as API6:2023 Unrestricted Access to Sensitive Business Flows and gives scenarios such as automated buying of a limited release to resell it, booking and cancelling most of a flight's seats, and farming a referral programme with generated accounts. Related patterns are limit overrun, SMS pumping, card testing and API abuse.

Test ideas

  • Find every action with a stated limit (five invites, three free exports, one trial, ten password resets per day) and try the limit plus one, from a single account and from a fresh one.
  • Check that the limit lives on the account or tenant, not only on the IP address or session.

What a good fix looks like

Count against the account, the tenant and, where it makes sense, the payment instrument, and store the counter server-side. Add cost-aware limits for expensive actions, and alert on unusual volumes so a person looks. Technical controls such as bot detection help, but OWASP is explicit that the business has to decide which flows are sensitive first. See also rate limiting.

How do you test race conditions and double-spend?

The rule: when two requests arrive at the same moment, the outcome is the same as if they arrived one after the other. A race condition breaks that. CWE-362 from MITRE covers the case where two pieces of code share a resource and the timing lets one change it while the other is mid-use. On the business side this appears as double spending a balance, using a one-time code twice, or withdrawing more than the account holds. A closely related bug class is time of check to time of use.

Test ideas

Choose the targets

  • Pick every "check, then change" action: redeem a code, spend a balance, claim a gift card, accept an invite, use the last item in stock, withdraw funds, vote.

Fire the requests

  • Send the same request ten to fifty times in parallel and count how many succeeded. PortSwigger teaches a three-step method (predict, probe, prove) and a single-packet technique that delivers 20-30 requests in one TCP packet, so network jitter cannot hide the race.
  • Repeat the test several times. A race may succeed one run in ten, so a single failed attempt proves nothing.

Reconcile the result

  • After the test, reconcile: balances, stock counts, redemption rows and ledger totals should agree with the number of successful responses.

Race-condition targets and the safe result

Run each target with parallel requests and compare with the expected result below.

TargetParallel testSafe result
Single-use couponRedeem 20 times at onceOne success, nineteen refusals
Wallet balanceWithdraw the full balance 10 times at onceBalance never below zero
Last unit of stockTwo buyers, one unitOne order, one refusal
RefundRefund the same order twice at onceOne refund, ledger agrees
Invite or seat limitSend invites past the plan limit togetherStops at the limit

What a good fix looks like

Make the check and the change one atomic step. Use a single conditional update (UPDATE ... WHERE balance >= amount), a database unique constraint on the redemption, a row lock inside a transaction, or an idempotency key, which Stripe documents as storing the first request's result and replaying it for any repeat. Do not rely on an in-memory check in one application instance when you run several. Then write a test that fires parallel requests and asserts the final totals.

Timing, expiry and time windows

The rule: time-based rules use the server clock and are checked at the moment of use.

Test ideas

  • Use an expired coupon, reset link, invite or download URL and confirm the server refuses it.
  • Change the device date or time zone and see whether any time-based decision follows the client.

What a good fix looks like

Store expiry as an absolute timestamp on the server, compare against server time when the action is performed, and test the boundary values. Treat any timestamp the client sends as information, never as a decision.

Ownership, roles and cross-account actions inside flows

Logic flaws and access control flaws overlap more than most checklists admit. A refund flow that works only for the buyer is a logic rule; a refund endpoint that accepts anyone's order ID is an access flaw that lives in the same rule. For each flow on your list, repeat the key steps with a second account and ask what it can reach that it should not.

  • Use account B to view, edit, cancel, refund or approve an object created by account A. This is the IDOR or BOLA family; see the IDOR checklist and broken object level authorization for detailed steps.
  • Use an ordinary account to call an admin or finance function directly. Hidden buttons are not a control.

The fix is the same one that fixes access control generally: check ownership and permission on the server for every action, using the identity from the session and never an ID from the request. The access control testing checklist covers how to plan accounts and record results.

How do you test files, payments and integrity checks?

Two more OWASP items belong on a product team's list because they touch real money and real data.

Uploads

For uploads, the rule is that the server accepts only the types and sizes it expects and never treats an upload as trusted. Test an unexpected file type, a file whose extension and content disagree, an oversize file and a file with an unexpected name. See file upload vulnerability for the technical side.

Payments and refunds

Payment checks

The rule is that fulfilment follows a verified payment event, not a browser redirect. Test these cases:

  • Open the "payment successful" URL directly without paying.
  • Replay or forge the provider's callback to your webhook. Is the signature verified, and is the event ID stored so it cannot be applied twice?
  • Pay a smaller amount, a different currency or a different order, and see whether fulfilment checks the amount and order reference.

Refund checks

  • Check refunds: partial refunds that add up to more than the payment, refunds after chargeback, and refund of a coupon-discounted order. See refund abuse.

For integrity checks, keep any value that matters later on the server, or sign it and verify it when it returns. Token tests belong in the API security testing guide.

What evidence should each test record?

A logic finding is only useful if someone else can reproduce it and a fix can be verified. Keep these six items for each case.

ItemWhat to write
RuleThe invariant, in one sentence
Accounts and stateWhich accounts, cart, balance or plan at the start
RequestsExact requests, with the one value you changed
Response and effectReply, then what the system did (order, balance, email)
Business effectWhat is lost and how often it can repeat
Outcome and dateWhether the control held

This is the structure a good pentest report uses; read a finding shows how to judge one. Rate severity by business effect and repeatability, and keep confidence separate.

How do you fix a logic flaw and keep it fixed?

Logic fixes are small in code and easy to undo by accident. Three habits keep them in place.

  • Turn each invariant into an automated test. "Total equals server-side prices", "code used once even in parallel", "step 3 refuses without step 2". These are cheap security regression tests and they run in your pipeline.
  • Add a rules review to design. When a ticket adds a discount, limit or state, ask what must always be true and what the worst repeated use is.
  • Re-test the exact exploit after the fix. A new scan does not prove a logic fix; running the same request sequence against the new code does. That is a closed-loop retest.
Five steps: write the invariant, break it on staging, prove it, fix on the server, replay the exact exploit.
Each rule goes round five steps; the last one becomes a regression test.

How often should you run this checklist, and who should?

Run the full list before a major launch and whenever a payment, promotion, onboarding or approval flow changes, and run invariant tests on every build. Have a specialist go through it at least once a year. Compare styles in black box vs grey box vs white box testing, and see the web application penetration testing checklist and the VAPT checklist.

Where Cyberlop fits

Cyberlop checks business-logic flaws and cross-account access as part of black-box, grey-box and white-box pentesting. In white-box mode it reads your code while testing the running app, so a finding can point to the file and line. It reports only what it actually exploited, with the request, the response and the evidence, and a fix is proven by re-running the exact exploit. See how it works and what the evidence looks like.

Infographic summarising the key takeaways: Write down your invariants first: a rule you cannot state is a rule you cannot test.; The server must decide p
The main points of this article in one view.

Questions people ask

Business logic testing checklist: FAQs

What is business logic testing?

Business logic testing checks that your application enforces its own rules when someone uses valid features in unexpected ways: changing a price, repeating a step, skipping a stage or sending requests at the same time. It looks for flaws in design and enforcement rather than in input handling.

What is the difference between a business logic flaw and an injection flaw?

An injection flaw lets an attacker put commands into a parser, and a scanner can spot the effect. A logic flaw uses normal requests that the app accepts because a rule is missing. The traffic looks legitimate, so a person or a rule-aware system has to judge the outcome.

Can automated tools find business logic vulnerabilities?

Only a small part. Tools can flag missing rate limits or obvious parameter changes, but they do not know what your prices, limits and workflows are meant to be. MITRE notes these errors are hard to detect automatically because they involve legitimate functionality. Plan for manual or rule-aware testing.

Which OWASP guide covers business logic testing?

The OWASP Web Security Testing Guide has a business logic chapter covering data validation, forged requests, integrity checks, process timing, usage limits, workflow circumvention, misuse defences, file uploads and payment functionality. The OWASP API Security Top 10 adds unrestricted access to sensitive business flows.

What is an example of a business logic vulnerability?

A checkout that trusts the price sent by the browser, a gift card that can be redeemed twice at the same moment, or a confirmation page that works without payment. The requests look normal; the missing rule is the flaw.

How is a business logic flaw different from IDOR?

IDOR is one cause of broken object-level access: swapping an ID to reach another account's object. A logic flaw is wider and covers order, limits, prices and timing. They overlap when a flow lets one account act on another's order.

See the IDOR entry and the IDOR checklist.

How do you test for race conditions in business logic?

Pick an action that checks then changes something, such as redeeming a code or spending a balance. Send the same request many times in parallel, repeat the run, then reconcile balances and records against the successes. Fix with atomic updates or unique constraints.

Does a business logic fix need a retest?

Yes. A new scan cannot show that a logic rule now holds. Re-run the exact request sequence that broke it, including the parallel version for races, and keep it as a regression test.

Cyberlop mark

Which of your rules would break?

Cyberlop checks business-logic flaws and cross-account access, and reports only what it actually exploited, with the request, the response and the line of code. A fix is proven by re-running the exact exploit. Ask us to run it on one of your applications.

Or start with a $199 pilot on one application: thirty days, success criteria agreed before day one, credited against the annual if you convert.