Race conditions are the category scanners miss the most, because their confirmation signal is statistical rather than syntactic. A single request either succeeds or fails; only a burst of requests against the same resource reveals whether a security invariant depends on timing. This is the time-of-check to time-of-use (TOCTOU) class — CWE-367 — and it routinely turns “redeem once” into “redeem fifty times”.
This playbook lays out the four-step method Pentrova uses to hunt race conditions, why a baseline matters, and how the result is reproduced rather than guessed.
Why race conditions evade normal scanners#
A conventional scanner reasons about one request at a time. It checks a response code, matches a pattern, moves on. A is invisible to that model because the bug is not in any single response — it is in what happens when many in-flight requests observe the same state before any of them commits a change. The window between the check (“does this user still have a coupon?”) and the use (“apply the coupon and decrement the count”) is where the exploit lives.
Step one: identify the state invariants#
Race conditions matter only where a state invariant must hold. Look for endpoints where “exactly once” or “no more than N” is a security property:
- Coupon and gift-card redemption
- Withdrawal, transfer, and payout requests
- Role transitions and invite acceptance
- Rate-limited logins and OTP verification
- Inventory decrement and seat allocation
These are business-logic invariants, the kind of application-specific finding a generic scanner can never ship because only the application knows what “broken” means.
Step two: capture the single-request baseline#
Before firing anything concurrent, capture how the endpoint behaves for one well-formed request. The baseline defines the shape of “normal” — status code, body shape, and the resulting state change. Without it, you cannot tell a genuine race from ordinary variance.
Step three: fire a coordinated burst#
Send a tight burst of identical requests timed to arrive inside the check-to-use window. Coordination matters: the requests must hit the server close enough together that they all pass the check before any of them completes the use.
baseline: POST /redeem {coupon: SAVE20} → 200 balance -20 (once)
burst×20: POST /redeem {coupon: SAVE20} → 200 ×14 (applied 14×)
→ 409 ×6
diff: 14 applications of a single-use coupon → race confirmed
Step four: diff against the baseline and re-confirm#
If the burst produces a response shape outside the baseline — multiple successful redemptions of a single-use coupon, a balance that goes negative, two role grants where one was expected — the race is exploitable. Pentrova’s verifier then checks that the divergence is reproducible across a second burst with a fresh baseline, so the finding is deterministic proof rather than a lucky timing artifact.
Running this safely#
A burst against a real endpoint can itself create real state — that is the whole point — so the agent only issues bursts against targets and profiles the customer has explicitly marked safe for the test, under sandbox guardrails. The recommended pattern is full burst testing in staging and conservative, scoped runs against production.
Remediation#
Race-condition fixes are usually small and well-understood:
- A database-level guard such as
SELECT … FOR UPDATEor an atomic conditional update. - A distributed lock (for example a Redis-backed lock) around the check-and-use sequence.
- An idempotency key so repeated requests collapse to a single effect.
The PoC bundle includes the baseline, the burst, the divergent responses, and the timing histogram, so the fix is easy to replay against the patched build.
Key takeaways#
- Race conditions are TOCTOU bugs: the exploit lives in the window between checking state and using it.
- Single-request scanners cannot see them; only a coordinated burst reveals the timing dependency.
- The method is identify invariants → baseline → burst → diff → re-confirm.
- Fixes are typically a row lock, a distributed lock, or an idempotency key.
FAQ#
What is the difference between a and a TOCTOU bug? TOCTOU (time-of-check to time-of-use) is the specific race where the state checked is no longer valid by the time it is used. It is the most common security-relevant class, and the one this playbook targets.
Why do I need a baseline before the burst? The baseline defines normal behaviour for a single request. Without it you cannot distinguish a genuine race (multiple successes that should be impossible) from ordinary response variance.
Is burst testing dangerous in production? It can create real state, so Pentrova restricts bursts to explicitly safe-marked targets and runs under guardrails. Full coverage belongs in staging; production runs are conservative and scoped.
See how business-logic and race testing fit the platform pipeline, or start a free engagement.