September 3, 2026
I Automated My Bug Bounty Recon Stack — Here’s the Exact Toolchain (2026)
A hands-on breakdown of the pipeline I run before I ever look at a target manually: subdomain enum → port scan → screenshot triage →…
By Bugitrix
7 min read
A hands-on breakdown of the pipeline I run before I ever look at a target manually: subdomain enum → port scan → screenshot triage → fuzzing — plus the exact script.
Six months ago, I was spending my first two hours on every new target doing the same repetitive grind: running subfinder, waiting, copy-pasting into httpx, waiting, manually eyeballing screenshots, waiting. By the time I actually got to testing, half my energy was gone.
So I sat down on a slow Sunday and turned the whole thing into one script. Not because automation is trendy — because I was tired of losing hours to busywork that a cron job could do while I slept.
This is that pipeline. Every command in this article is one I actually run. No theory, no "best practices" fluff — just the exact toolchain, in the exact order, with the exact flags I use, and the reasoning behind each decision.
The Problem With Most Recon Guides
Most recon write-ups show you a tool list and call it a methodology. A tool list is not a methodology. The order you run things in, what you filter out at each stage, and how you route output into the next tool is what actually determines whether you find something or drown in noise.
Here's the mistake I made for the first year of doing this: I ran every tool against every subdomain, generated a mountain of data, and then had no system to actually act on it. Recon isn't about collecting more data — it's about collecting the right data and cutting it down fast enough that you still have energy left to test.
So the pipeline below is built around one rule: at every stage, kill dead weight before it reaches the next tool.
Stage 1 — Subdomain Enumeration
Goal: get the widest possible attack surface without wasting time on sources that return garbage.
I run three tools in parallel and merge the output, because no single source is complete.
bash
# Passive sources
subfinder -d target.com -all -recursive -silent -o subfinder.txt
# Certificate transparency + archive-based
assetfinder --subs-only target.com > assetfinder.txt
# Github/dorking-based recon for orgs with public repos
github-subdomains -d target.com -t $GITHUB_TOKEN -o github.txt
# Merge + dedupe
cat subfinder.txt assetfinder.txt github.txt | sort -u > all_subs.txt# Passive sources
subfinder -d target.com -all -recursive -silent -o subfinder.txt
# Certificate transparency + archive-based
assetfinder --subs-only target.com > assetfinder.txt
# Github/dorking-based recon for orgs with public repos
github-subdomains -d target.com -t $GITHUB_TOKEN -o github.txt
# Merge + dedupe
cat subfinder.txt assetfinder.txt github.txt | sort -u > all_subs.txtWhy three tools, not one: subfinder is strong on passive DNS and cert transparency, assetfinder catches things subfinder occasionally misses from Wayback/CommonCrawl, and github-subdomains has pulled internal-looking hostnames out of leaked config files for me more than once. On a recent target this combo returned 340 subdomains vs. 210 from subfinder alone — that 130-subdomain gap is where the less-tested stuff usually lives.
Practical tip: if the program scope allows it, add a permutation step. Tools like dnsgen or alterx generate likely variations (dev-target.com, target-staging.com, api-v2.target.com) that passive sources never surface because they were never publicly indexed.
bash
cat all_subs.txt | dnsgen - | dnsx -silent -o permuted_live.txtcat all_subs.txt | dnsgen - | dnsx -silent -o permuted_live.txtThis single step has found me more staging/dev environments than every passive source combined.
Stage 2 — Resolve and Filter Dead Hosts
No point scanning subdomains that don't resolve. This step alone can cut your list by 30–50%.
bash
cat all_subs.txt | dnsx -silent -resp-only -o resolved.txtcat all_subs.txt | dnsx -silent -resp-only -o resolved.txtNow you have a clean, live-only list. This is the list everything downstream will use — never feed unresolved hosts into a port scanner, it's a pure waste of time and rate limit.
Stage 3 — Port Scanning
Goal: find services beyond 80/443. This is where people get lazy, and it's where a lot of low-hanging fruit lives — exposed admin panels, dev APIs on nonstandard ports, forgotten Jenkins instances.
bash
naabu -l resolved.txt -top-ports 1000 -silent -o ports.txtnaabu -l resolved.txt -top-ports 1000 -silent -o ports.txtI don't full-port-scan (1–65535) every target by default — it's slow and most programs rate-limit hard enough that it burns your whole session. I run top-1000 first, triage what I find, and only go full-range on hosts that look genuinely interesting (unusual naming, subdomains like internal-, vpn-, dev-, staging-).
bash
# Full range, only on shortlisted hosts
naabu -l shortlisted.txt -p - -silent -o full_ports.txt# Full range, only on shortlisted hosts
naabu -l shortlisted.txt -p - -silent -o full_ports.txtReal example: on a recon run last quarter, a host named partner-api-old.target.com returned nothing interesting on ports 80/443, but a full scan turned up an exposed port 8081 running an outdated internal dashboard with default creds still active. That single decision — to full-scan a suspiciously-named host instead of skipping it — was worth more than the rest of that day's recon combined.
Stage 4 — HTTP Probing
Now take the live hosts + open ports and figure out what's actually running an HTTP service, and gather metadata (status code, title, tech stack, response size) in one pass.
bash
cat resolved.txt | httpx -silent -status-code -title -tech-detect \
-follow-redirects -o httpx_output.txtcat resolved.txt | httpx -silent -status-code -title -tech-detect \
-follow-redirects -o httpx_output.txtI always pull -tech-detect here. Knowing a host runs an old WordPress version or a specific JS framework tells you which fuzzing wordlists and which nuclei templates to prioritize later — it saves you from blindly firing every template at every host.
Stage 5 — Screenshot Triage
This is the step people skip and shouldn't. Visual triage is how you catch login panels, admin dashboards, error pages leaking stack traces, and default install pages — fast, without reading raw HTTP responses one by one.
bash
cat httpx_output.txt | gowitness file -f - --threads 20cat httpx_output.txt | gowitness file -f - --threads 20I go through the screenshot gallery and manually flag anything that looks like:
- A login page with a non-standard framework (custom admin panels > generic SaaS logins)
- A default "It works!" or install wizard page
- Anything returning a stack trace or verbose error on the homepage
- Old-looking UI (a visual signal for outdated, unmaintained software)
This step takes 10–15 minutes and routinely tells me where to spend the next three hours. Don't skip it to save time — it saves you time.
Stage 6 — Content Discovery & Fuzzing
Only on the hosts that survived triage. Fuzzing everything is how people get IP-banned and burn their rate limit on hosts that had nothing interesting to begin with.
bash
ffuf -u https://FUZZ.target.com \
-w subdomains_wordlist.txt -mc 200,301,302,403 \
-t 40 -o vhost_fuzz.json
ffuf -u https://target.com/FUZZ \
-w /path/to/seclists/Discovery/Web-Content/raft-large-directories.txt \
-mc 200,301,302,403 -t 40 -recursion -recursion-depth 2 \
-o dir_fuzz.jsonffuf -u https://FUZZ.target.com \
-w subdomains_wordlist.txt -mc 200,301,302,403 \
-t 40 -o vhost_fuzz.json
ffuf -u https://target.com/FUZZ \
-w /path/to/seclists/Discovery/Web-Content/raft-large-directories.txt \
-mc 200,301,302,403 -t 40 -recursion -recursion-depth 2 \
-o dir_fuzz.jsonWordlist choice matters more than tool choice here. Generic wordlists find generic paths. If httpx told you a host is running a specific tech stack, use a stack-specific wordlist (e.g., SecLists has dedicated lists for WordPress, Laravel, Spring Boot, etc.) — you'll get far higher signal-to-noise.
Stage 7 — Vulnerability Scanning With Nuclei
Last step, and only after everything above has been filtered down to a manageable, high-value target list.
bash
cat httpx_output.txt | nuclei -silent \
-t exposures/ -t misconfiguration/ -t default-logins/ -t cves/ \
-severity medium,high,critical \
-o nuclei_results.txtcat httpx_output.txt | nuclei -silent \
-t exposures/ -t misconfiguration/ -t default-logins/ -t cves/ \
-severity medium,high,critical \
-o nuclei_results.txtImportant habit: update your nuclei templates every single run. New CVEs land constantly, and templates get added within days of public disclosure. A stale template repo is the single biggest reason people report "nuclei found nothing" on a target that actually had something.
bash
nuclei -update-templatesnuclei -update-templatesI also keep a small folder of custom templates for patterns I've noticed repeatedly across programs — things generic templates don't catch because they're specific to how certain frameworks misconfigure things. Writing your own templates, even simple ones, is one of the highest-leverage skills you can build in this field.
The Full Script
Here's the whole thing wired together. Save it as recon.sh, give it execute permission, and run ./recon.sh target.com.
bash
#!/bin/bash
# bugitrix recon pipeline v2 — subdomain -> port -> screenshot -> fuzz -> nuclei
TARGET=$1
OUTDIR="recon_$TARGET"
mkdir -p $OUTDIR && cd $OUTDIR
echo "[+] Subdomain enumeration"
subfinder -d $TARGET -all -recursive -silent -o subfinder.txt
assetfinder --subs-only $TARGET > assetfinder.txt
cat subfinder.txt assetfinder.txt | sort -u > all_subs.txt
echo "[+] Resolving live hosts"
cat all_subs.txt | dnsx -silent -o resolved.txt
echo "[+] Port scanning (top 1000)"
naabu -l resolved.txt -top-ports 1000 -silent -o ports.txt
echo "[+] HTTP probing"
cat resolved.txt | httpx -silent -status-code -title -tech-detect \
-follow-redirects -o httpx_output.txt
echo "[+] Screenshotting"
cat httpx_output.txt | gowitness file -f - --threads 20
echo "[+] Directory fuzzing on live hosts"
while read -r url; do
ffuf -u "${url}/FUZZ" -w /path/to/seclists/Discovery/Web-Content/raft-large-directories.txt \
-mc 200,301,302,403 -t 40 -o "fuzz_$(basename $url).json" -silent
done < httpx_output.txt
echo "[+] Nuclei scan"
nuclei -update-templates -silent
cat httpx_output.txt | nuclei -silent \
-t exposures/ -t misconfiguration/ -t default-logins/ -t cves/ \
-severity medium,high,critical -o nuclei_results.txt
echo "[+] Done. Check $OUTDIR for all output."#!/bin/bash
# bugitrix recon pipeline v2 — subdomain -> port -> screenshot -> fuzz -> nuclei
TARGET=$1
OUTDIR="recon_$TARGET"
mkdir -p $OUTDIR && cd $OUTDIR
echo "[+] Subdomain enumeration"
subfinder -d $TARGET -all -recursive -silent -o subfinder.txt
assetfinder --subs-only $TARGET > assetfinder.txt
cat subfinder.txt assetfinder.txt | sort -u > all_subs.txt
echo "[+] Resolving live hosts"
cat all_subs.txt | dnsx -silent -o resolved.txt
echo "[+] Port scanning (top 1000)"
naabu -l resolved.txt -top-ports 1000 -silent -o ports.txt
echo "[+] HTTP probing"
cat resolved.txt | httpx -silent -status-code -title -tech-detect \
-follow-redirects -o httpx_output.txt
echo "[+] Screenshotting"
cat httpx_output.txt | gowitness file -f - --threads 20
echo "[+] Directory fuzzing on live hosts"
while read -r url; do
ffuf -u "${url}/FUZZ" -w /path/to/seclists/Discovery/Web-Content/raft-large-directories.txt \
-mc 200,301,302,403 -t 40 -o "fuzz_$(basename $url).json" -silent
done < httpx_output.txt
echo "[+] Nuclei scan"
nuclei -update-templates -silent
cat httpx_output.txt | nuclei -silent \
-t exposures/ -t misconfiguration/ -t default-logins/ -t cves/ \
-severity medium,high,critical -o nuclei_results.txt
echo "[+] Done. Check $OUTDIR for all output."Run it, go make coffee, come back to a folder with subdomains, live hosts, open ports, screenshots, fuzzing results, and nuclei findings — all in one directory, all named clearly. From there, you're testing, not collecting.
What Automation Doesn't Replace
I want to be honest about this because too many people read "I automated recon" and think it means they can skip learning the fundamentals. It doesn't.
The script above gets you data. It does not tell you which finding is actually exploitable, which "vulnerability" nuclei flagged is a false positive, or which weird subdomain naming convention is worth a manual deep-dive. That judgment only comes from doing manual testing first, understanding why each tool works the way it does, and building the pattern recognition that no script can give you.
Automate the repetitive 80%. Spend your saved time on the 20% that actually requires a human brain — manual testing, business logic flaws, chaining low-severity findings into something critical. That's where the real bounties are, and no tool will ever do that part for you.
Where I Learned to Build Pipelines Like This
I didn't figure this workflow out by reading one blog post — it came from a lot of trial, error, wasted API credits, and rate-limit bans early on. If you're at the stage where you're collecting tools but not sure how to turn them into an actual system (or you're finding recon data but not converting it into reports), that gap is exactly what I work on with people 1:1.
If that's useful to you, a few ways to go from here:
- 1:1 Mentorship — I work directly with people building their bug bounty skillset from the ground up: methodology, tooling, report writing, the whole pipeline. Apply here
- Resume, LinkedIn & Portfolio Building — if you're trying to break into a security role and your resume doesn't reflect the skills you actually have, this is a focused service to fix that. Get started here
- Telegram channel — I post daily practical tips, free wordlists, and recon findings breakdowns. No noise, just things I'd want to read myself. Join here
- Everything else — courses, resources, and updates live at bugitrix.com
Final Thoughts
The toolchain above isn't special because of the tools — subfinder, httpx, naabu, and nuclei are things most of you already have installed. It's the order, the filtering at each stage, and the discipline to only spend manual time on hosts that earned it, that turns a pile of tools into an actual methodology.
Copy the script, run it against your next target, and adjust the filtering thresholds to match your own risk tolerance and time budget. That's the whole point of automating this stuff — not to replace your brain, but to buy it more time to do the part that actually matters.
Good luck out there. Happy hunting.
— Bugitrix