These notes are public, opinionated, and evolving — read abdelkader.ma for the long-form posts.
Bug BountyRecon Checklist

Recon Checklist

Recon is not “find as many subdomains as possible.” It is “find the assets that are most likely to be vulnerable fastest.” This is the order I run.

1. Scope mapping (5 min)

Before any tool runs, list:

  • Apex domains in scope
  • Wildcards (*.target.com?)
  • Out-of-scope subdomains (often support.target.com, status.target.com)
  • Out-of-scope severities (SPF/DMARC, self-XSS, etc.)

Putting this in scope.txt and out-of-scope.txt saves an hour of triage arguing later.

2. Subdomain enumeration

Three sources, three rounds:

# Passive (CT logs, public DNS)
subfinder -d target.com -all -recursive -o subs.txt
amass enum -passive -d target.com >> subs.txt
curl -s "https://crt.sh/?q=%25.target.com&output=json" | jq -r '.[].name_value' >> subs.txt
 
# Resolve to filter the noise
sort -u subs.txt > subs-uniq.txt
dnsx -l subs-uniq.txt -resp -silent > subs-resolved.txt
 
# Active brute (only if scope allows)
puredns bruteforce wordlists/best-dns-wordlist.txt target.com >> subs-resolved.txt

3. Port + service scan on live hosts

naabu -l alive.txt -top-ports 1000 -silent -o ports.txt
nmap -iL alive.txt -sV -sC -p$(cut -d: -f2 ports.txt | sort -u | paste -sd,) -oA scan

For non-standard ports specifically: that is where the dev/staging app the team forgot about lives.

4. HTTP probing + screenshotting

httpx -l subs-resolved.txt -title -tech-detect -status-code -o http.txt
gowitness scan file --file alive-urls.txt --threads 50

I never start manual testing without looking at the screenshots first. Branding, login forms, and admin panels are visible in seconds. The page that looks “different” is almost always where the bug is.

5. Asset discovery on each host

Per app:

# Tech fingerprint
whatweb https://app.target.com
 
# JS endpoints (the goldmine)
gau https://app.target.com | grep -E "\.js$" | sort -u > js.txt
katana -u https://app.target.com -d 3 -jc -o crawled.txt
 
# Extract endpoints + secrets from JS
cat js.txt | xargs -I {} curl -s {} | grep -oE "(/[a-zA-Z0-9_/-]+)" | sort -u > endpoints.txt
trufflehog filesystem ./js --json

90% of high-impact bug bounty findings I see come from parsing JavaScript for endpoints the developer thought were “internal.” If you skip JS recon, you ship duplicates.

6. Content discovery per app

ffuf -u https://app.target.com/FUZZ \
     -w wordlists/raft-medium-words.txt \
     -mc 200,204,301,302,401,403 \
     -fc 404 -fs <stable-size-of-default-404> \
     -o ffuf.json -of json

The -fs filter on the default-404 size is the difference between a useful result list and 50k lines of noise.

7. The parts most people skip

These pay off more than they should:

  • Source map filesapp.js.map in production reveals the original source tree. Search for it on every JS endpoint.
  • /.git/ directory exposuregitdumper it; you get the full history.
  • /.env filesffuf with .env, .env.local, .env.production.
  • Backup files.bak, .old, .zip, .swp on common paths.
  • GraphQL introspectionPOST /graphql with {__schema{types{name}}}. If it answers, you have the whole API.
  • Login endpoints with rate limits per IP only — header-based bypasses (X-Forwarded-For, X-Real-IP, True-Client-IP).
  • Email signup with +me+admin@target.com sometimes lands in admin inboxes.

8. What goes into the report

For each finding I capture, in this order:

  1. Repro URL + minimal repro steps — 3 lines max
  2. Impact — what an attacker can actually do, not “could potentially lead to”
  3. Evidence — screenshot + curl repro
  4. Suggested fix — short, specific, no “use a WAF”

Programs pay faster when the triage engineer doesn’t have to write your bug for you.