BB_Workflow tool

One-command, passive-first bug bounty recon

The first day of any bug bounty engagement is always the same six moves: pull subdomains, check whether the domain fakes DNS answers, resolve what came back, see what actually serves HTTP, look at what those endpoints run, and write somewhere before the terminal scrollback buries it. I ran that loop by hand, per target, for long enough to get tired of it — so I packaged it.

bb_workflow is that loop as a single command. Free, open source (MIT), Python, and deliberately boring in the places where a recon tool should be boring.

Passive by default, active only on request

This is the design decision the whole tool hangs on. Bug bounty rules are uneven about scanning, but they are never casual about it — an active scan against something the program did not list is how an account gets triage suspended. So the default run is passive:

text
subdomains → wildcard → resolve → webprobe → techdetect

No port scan, no directory busting, no vulnerability scanning unless you ask for each one explicitly:

bash
python3 bb_workflow.py target.com --portscan --vulnscan --dirbust

And if you passed those flags on autopilot and then remembered the program only allows passive testing, there is a hard override:

bash
python3 bb_workflow.py target.com --passive-only

--passive-only strips any active phase from the run, even ones you passed on the command line. It exists because the safe version of a command should be the easiest one to reach for, not the one you have to reconstruct from memory.

The phases

Phase What it does Default?
subdomains passive discovery from crt.sh, amass and (if present) theHarvester — merged, deduplicated yes
wildcard probes a random label to detect wildcard DNS, so you know when your subdomain list is padded with noise yes
resolve DNS resolution of every candidate host yes
webprobe parallel HTTP(S) probing — status, final URL, title, headers, built-in tech signatures yes
techdetect whatweb fingerprinting of live endpoints yes
portscan nmap top-ports against resolved hosts opt-in
dirbust gobuster directory busting opt-in
vulnscan nuclei against live endpoints opt-in

Every phase can also be addressed directly — --steps subdomains webprobe runs only what you name, --skip portscan drops what you do not want. The external tools (amass, nmap, whatweb, gobuster, nuclei) are auto-detected and gracefully skipped when missing; the pipeline itself needs Python 3.9+ and requests, nothing else.

The scope file is the safety rail

Recon tools fail in a specific way: they happily enumerate and touch whatever you point them at, and scope discipline lives entirely in your head. This one takes the program's in-scope names as an argument:

bash
python3 bb_workflow.py target.com --scope-file scope.txt

scope.txt is one domain per line, straight from the program's scope page. Anything found outside those names is dropped before probing — and if the target you passed is itself not covered by the file, the run refuses to start and exits with an error instead of quietly proceeding. The wildcard check serves the same discipline from the other direction: knowing that *.target.com answers for every fake label saves you from celebrating a subdomain list that is mostly DNS fiction.

The output is the point

Everything lands in reports/<target>/:

text
subdomains.txt    resolved.txt     live_hosts.json
live_urls.txt     technologies.txt report.json
summary.md        run.log

summary.md is the triage view — surface counts, live endpoints with titles and status codes, findings if any. report.json holds the same data machine-readable, so a later script can consume it without scraping terminals. run.log is the audit trail of what ran, when, and what it returned. live_urls.txt feeds straight into nuclei -l when you decide the program allows a scan.

The rule I built it around: no result should exist only in your scrollback. Half of wasted bounty time is not the recon itself — it is not being able to reconstruct what you already found three hours later.

What a run actually looks like

A real default run, executed today against example.com:

shell-session
$ python3 bb_workflow.py example.com
bb_workflow v0.2.1 -> target example.com
  steps: subdomains, wildcard, resolve, webprobe, techdetect

=> subdomain discovery (passive: crt.sh + amass + theHarvester)
  1 unique in-scope hosts
=> wildcard DNS check
  no wildcard (random probe did not resolve)
=> web probing (parallel HEAD+GET)
  200 https://example.com/  [Example Domain] [server:cloudflare]

== summary ==
  report written: reports/example.com/summary.md
  machine data:   reports/example.com/report.json

done. results in reports/example.com/

Ten seconds end to end — because example.com is a tiny surface. On a real program the same command takes longer in proportion to what the sources return; the phases and the artifacts are identical. The point of showing this run is that every number above came out of the tool, not out of a draft I wrote around a wish.

What it does not do

It does not exploit anything, does not decide what is in scope for you (the program's rules do that, and the file you feed it only reflects them), and it does not replace the part of the job that actually finds bugs — reading, guessing, and chaining what the recon surfaced. It handles the repetitive half so the interesting half gets the hours.

Get it

bash
git clone https://github.com/rur1k1d/bb_workflow
pip install -r requirements.txt
python3 bb_workflow.py example.com

MIT licensed. The README carries the full phase reference and the ethical-use reminders — including the only line that matters: the tool grants no permission by itself; the program's terms do.


If you run it against an in-scope target and hit a rough edge, the issue tracker on the repo is the right place — or use the contact form on the main site, that one works too, I tested it.