$npx -y skills add elementalsouls/Claude-BugHunter --skill hunt-race-conditionHunting skill for race condition vulnerabilities. Built from 12 public bug bounty reports including modern HTTP/2 single-packet attack cases (James Kettle DEF CON 2023 "Smashing the State Machine"; RyotaK / Flatt Security 10,000-request first-sequence-sync expansion 2024). Covers
| 1 | ## Firing a race — two primitives (tooling-agnostic) |
| 2 | |
| 3 | Winning a race needs requests that arrive in the *same* narrow window — sequential sends never |
| 4 | work. Use a single-packet / synchronized-send tool: **Burp Repeater** "Send group in parallel" |
| 5 | (HTTP/2 single-packet attack), **Turbo Intruder** (`engine=Engine.BURP2`, `gate` sync), or any |
| 6 | client that can flush N requests simultaneously. Two shapes: |
| 7 | |
| 8 | - **Identical-copies race** — fire N IDENTICAL copies of one request at once (limit-overrun: |
| 9 | double-spend a coupon/gift-card, exceed a one-per-user quota). Success = ≥2 of the N return 2xx. |
| 10 | - **Different-requests race (partial construction)** — fire a LIST of DIFFERENT requests in one |
| 11 | synchronized window, repeated over several rounds. For register-then-confirm / TOCTOU races |
| 12 | where the object exists in a usable state mid-creation. Example (email-verification bypass — |
| 13 | register an arbitrary email, then confirm it through the construction window with a blank token): |
| 14 | ``` |
| 15 | Request A: POST /register body: csrf=<csrf>&username=hacker&email=anything@exploit.net&password=pw |
| 16 | Request B: GET /confirm params: token= (empty) |
| 17 | Fire A and B together, repeat ~20 rounds. |
| 18 | ``` |
| 19 | Get a fresh CSRF from `GET /register` first, then fire the batch. After it succeeds, log in as the |
| 20 | new account and perform the objective (e.g. a state-changing admin action such as deleting a user). |
| 21 | The blank-token confirm wins during the window where the user row exists but its verification |
| 22 | token isn't set yet. |
| 23 | |
| 24 | ## Crown Jewel Targets |
| 25 | |
| 26 | Race conditions are high-severity findings because they break financial, access control, and integrity assumptions that defenders rarely stress-test. Highest payouts come from: |
| 27 | |
| 28 | - **Monetary/credit systems** — double-spending gift cards, coupons, referral bonuses, promotional credits, wallet balances |
| 29 | - **Vote/reputation manipulation** — upvoting the same content multiple times, gaming leaderboards or trending algorithms |
| 30 | - **Account limits bypass** — exceeding free-tier quotas, bypassing "one per user" restrictions on invites, trial activations, or API key generation |
| 31 | - **Privilege escalation** — racing role assignment or permission checks during user creation/upgrade flows |
| 32 | - **Deletion bypass** — reading or exfiltrating data during a narrow window between "marked for deletion" and "actually deleted" |
| 33 | - **Payment flows** — charging a card once but receiving multiple fulfillments |
| 34 | |
| 35 | **Best-paying asset types:** Fintech apps, SaaS platforms with credit/subscription models, social platforms with reputation systems, e-commerce checkout flows, OAuth/SSO token endpoints. |
| 36 | |
| 37 | --- |
| 38 | |
| 39 | ## Attack Surface Signals |
| 40 | |
| 41 | ### URL Patterns |
| 42 | ``` |
| 43 | /vote, /upvote, /like, /favorite |
| 44 | /redeem, /apply-coupon, /use-code, /claim |
| 45 | /purchase, /checkout, /confirm-order, /pay |
| 46 | /transfer, /withdraw, /send-money |
| 47 | /invite, /referral, /accept-invite |
| 48 | /upgrade, /activate, /trial |
| 49 | /delete, /deactivate, /cancel |
| 50 | /follow, /subscribe |
| 51 | ``` |
| 52 | |
| 53 | ### Response Headers That Signal Race-Prone Backends |
| 54 | ``` |
| 55 | X-RateLimit-* # rate limiting exists, but may not be atomic |
| 56 | X-Request-Id # each request independently tracked |
| 57 | No Cache-Control # stateful ops not idempotent |
| 58 | ``` |
| 59 | |
| 60 | ### JavaScript Patterns to Grep |
| 61 | ```javascript |
| 62 | // Single-use action buttons with client-side disable |
| 63 | button.disabled = true |
| 64 | $('#btn').prop('disabled', true) |
| 65 | // Optimistic UI updates (state set before server confirms) |
| 66 | setState({ used: true }) |
| 67 | // Sequential async calls without locking |
| 68 | await useVoucher(); await deductBalance(); |
| 69 | ``` |
| 70 | |
| 71 | ### Tech Stack Signals |
| 72 | - **Ruby on Rails** without `with_lock` / `lock!` — ActiveRecord doesn't lock by default |
| 73 | - **Node.js** with async/await chains — non-atomic DB reads then writes |
| 74 | - **PHP** without `SELECT ... FOR UPDATE` — common in legacy codebases |
| 75 | - **Microservices** — inter-service calls introduce natural TOCTOU windows |
| 76 | - **Redis counters** without Lua scripts or `INCR` atomicity checks |
| 77 | - **Message queues** — idempotency keys often missing |
| 78 | |
| 79 | --- |
| 80 | |
| 81 | ## Step-by-Step Hunting Methodology |
| 82 | |
| 83 | 1. **Enumerate one-time or limited-use actions** — Map every endpoint that enforces a "once per user", "limited quantity", or "deduct balance" constraint. These are your primary targets. |
| 84 | |
| 85 | 2. **Understand the state machine** — For each target action, identify: (a) |