Race Conditions & TOCTOU - Hunter Knowledge Base
SkillFiles & storageKnowledge base for finding race conditions and TOCTOU flaws - concurrent requests exploiting non-atomic check-then-act logic (double-spend, limit bypass, balance manipulation, file TOCTOU). Use when hunting concurrency/business-logic race bugs. CWE-362/367/366, OWASP A04:2021-Insecure Design.
Available today. Use it from your connected AI after setup.
No other account needed.
Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
Then ask your AI: use the Race Conditions & TOCTOU - Hunter Knowledge Base skill
What this skill tells your AI
The instructions your AI receives, as published by dmdhrumilmistry/security-harness in skills/sh-kb-race-conditions/SKILL.md and read by ahel’s review.
A gap between checking a condition and acting on it lets concurrent requests slip through: spend a coupon twice, withdraw more than the balance, bypass a rate/quota limit, or swap a file between check and use. These are logic bugs - reason about interleavings, not just about a dangerous sink.
Classic patterns to hunt
- Check-then-act on shared state without a lock/transaction/atomic op: read balance -> if enough -> subtract; check "coupon unused" -> mark used; check "invite not redeemed" -> redeem.
- Limit/quota bypass: "only once" / "max N" enforced by a non-atomic read+increment; parallel requests all pass the check before any writes.
- Financial double-spend: withdraw/transfer/refund without row locking or a DB constraint.
- TOCTOU on filesystem (CWE-367):
os.path.exists/access()thenopen(); symlink swapped in between. - Idempotency gaps: ret/replay of a request causes duplicate side effects (no idempotency key).
- Auth/session races: token validated then state changes; concurrent login/session mutation.
Sinks / patterns (grep targets)
Non-atomic sequences: a SELECT/read followed by an UPDATE/write of the same field without a transaction,
SELECT ... FOR UPDATE, optimistic-lock version, or atomic DB op. Grep near money/credits/quota/inventory:
balance|credit|quota|limit|coupon|voucher|stock|inventory|redeem|withdraw|transfer. Filesystem:
os.path.exists|access\(|stat\( shortly before open(. Look for absence of with transaction,
SELECT FOR UPDATE, lock, Mutex, atomic, unique constraints.
Detection recipe
- Identify state-changing operations on shared/limited resources from
codebase-map.json. - For each, read the handler: is the check-and-act atomic? (single UPDATE with a WHERE guard, DB constraint, row lock, or app-level lock?) If it's read-then-write across statements with no lock, flag.
- Note whether the endpoint is reachable concurrently (most HTTP handlers are).
PoC / evidence
- Describe the interleaving: "N parallel
POST /redeemrequests, all readused=falsebefore any writesused=true, so all N succeed." Show the non-atomic code path. - Practical PoC: fire many concurrent identical requests (e.g. 20-50 in parallel) and observe the invariant
broken (balance negative, coupon used twice). Often
needs-runtimeto fully confirm. - Tightening the race window: naive parallel requests over separate TCP connections suffer network
jitter that can hide a narrow window. Over HTTP/2, a "single-packet attack" (send 20-30 request streams
in one TCP packet so the server receives them effectively simultaneously) removes that jitter; over
HTTP/1.1 a "last-byte sync" (send all but the final byte of each request, then release the final bytes
together) achieves the same effect. Tools: Burp Repeater's parallel "group" send, or Turbo Intruder
(
engine=Engine.BURP2,concurrentConnections=1). When racing multiple different endpoints (e.g. check-balance vs. spend), pre-warm each connection with a throwaway request first so backend processing times align, since cross-endpoint timing skew is a common reason an otherwise-real race fails to trigger.
False-positive filters
- The critical section is atomic: single
UPDATE ... SET x=x-1 WHERE x>0(check in the WHERE), DB unique constraint /SELECT ... FOR UPDATE, optimistic locking (version column),INSERT ... ON CONFLICT, or an explicit lock/mutex/serializable transaction covering check+act. - The resource isn't shared across requests, or the operation is naturally idempotent.
- A single-writer queue / actor serializes the operation.
CWE / OWASP / severity
CWE-362 (race), CWE-367 (TOCTOU), CWE-366. OWASP A04:2021 (Insecure Design). Financial/limit bypass -> high/critical by value; filesystem TOCTOU -> high if it leads to privilege gain.
Chaining hints
Race to bypass a spend/limit -> monetary loss; combine with access-control (race a permission change);
TOCTOU file swap -> path-traversal/privilege escalation. Often amplifies an otherwise-bounded feature.
Mitigation
Make check-and-act atomic: guard in the UPDATE WHERE, use DB constraints/unique indexes, row locking
(SELECT ... FOR UPDATE) or optimistic locking, serializable transactions, idempotency keys for retried
mutations, and atomic counters for quotas. Avoid exists-then-open; open directly and handle errors.
Signals
- GitHub stars
- 26
- Forks
- 9
- Last commit
- Sep 2026
Advanced
- Item type
- skill
- Key
sh-kb-race-conditions- Source
- github.com/dmdhrumilmistry/security-harness