The Hook
Most recon tools for bug bounty hunting come with a 30-minute setup ritual: install Go, clone a dozen repos, wrestle with module dependencies, and pray nothing breaks. I got tired of it. So I built a subdomain enumerator, live host prober, and vulnerability scanner — in 280 lines of pure Python, with zero external dependencies. It runs on a $35 Raspberry Pi and starts producing results in under 5 seconds.
Here's what it looks like in action:
# Enumerate subdomains for a target
$ python3 bb_kit.py enum tesla.com
[*] Enumerating tesla.com...
shop.tesla.com
api.tesla.com
auth.tesla.com
[...]
[+] Found 247 subdomains
# Probe which ones are actually alive
$ python3 bb_kit.py probe shop.tesla.com api.tesla.com auth.tesla.com
https://shop.tesla.com [200] nginx
https://auth.tesla.com [200] cloudflare
http://api.tesla.com [403] nginx/1.18
# Quick vulnerability scan
$ python3 bb_kit.py scan https://example.com
[*] Scanning https://example.com
[!] EXPOSED: https://example.com/.git/config
[!] SECURITY.TXT: https://example.com/.well-known/security.txt
No Docker, no go install, no npm. Just Python 3.8+ and you're hunting.
Why Build This?
The bug bounty tool ecosystem is dominated by Go-based tools: subfinder, amass, httpx, nuclei. They're great, but:
| Tool | Language | External Dependencies |
|---|---|---|
| subfinder | Go | Go toolchain, 50+ modules |
| amass | Go | Go toolchain, DNS libraries |
| httpx | Go | Go toolchain, HTTP stack |
| bb-automation-kit | Python | None (stdlib only) |
I wanted something I could drop onto any machine — cloud VM, Raspberry Pi, even a locked-down corporate laptop — and have it work immediately. No compilation. No $GOPATH gymnastics. Just python3 bb_kit.py enum target.com and go.
How It Works (The Code)
The core is refreshingly simple. Here's the subdomain enumeration engine — it queries crt.sh (Certificate Transparency logs) and urlscan.io in parallel, deduplicates results, and returns a clean list:
def enum_subdomains(domain):
"""Discover subdomains from crt.sh and urlscan.io"""
subs = set()
# crt.sh — Certificate Transparency logs
url = f"https://crt.sh/?q=%.{domain}&output=json"
req = urllib.request.Request(url, headers={'User-Agent': 'BB-Kit/1.0'})
data = json.loads(urllib.request.urlopen(req, timeout=20).read())
for entry in data:
name = entry.get('name_value', '').lower().strip()
for n in name.split('\n'):
n = n.strip().lstrip('*.')
if n.endswith(domain) and n != domain:
subs.add(n)
# urlscan.io — passive DNS
url = f"https://urlscan.io/api/v1/search/?q=domain:{domain}"
req = urllib.request.Request(url, headers={'User-Agent': 'BB-Kit/1.0'})
data = json.loads(urllib.request.urlopen(req, timeout=15).read())
for result in data.get('results', []):
page_domain = result.get('page', {}).get('domain', '')
if page_domain.endswith(domain):
subs.add(page_domain)
return sorted(subs)
The live prober uses ThreadPoolExecutor for parallel HTTP checks — 10 hosts at a time:
def probe_host(host):
"""Check if a host is live via HTTP/HTTPS"""
for scheme in ['https', 'http']:
try:
req = urllib.request.Request(
f"{scheme}://{host}",
headers={'User-Agent': 'BB-Kit/1.0'}
)
resp = urllib.request.urlopen(req, timeout=5)
return {
'host': host,
'url': f'{scheme}://{host}',
'status': resp.status,
'server': resp.headers.get('Server', 'unknown')
}
except urllib.error.HTTPError as e:
return {
'host': host, 'url': f'{scheme}://{host}',
'status': e.code,
'server': e.headers.get('Server', '?')
}
except:
pass
return {'host': host, 'url': None, 'status': 0, 'server': 'unreachable'}
def probe_hosts(hosts, threads=10):
"""Probe multiple hosts in parallel"""
with ThreadPoolExecutor(max_workers=threads) as executor:
futures = {executor.submit(probe_host, h): h for h in hosts}
return [f.result() for f in as_completed(futures)]
And the vulnerability scanner checks for low-hanging fruit — exposed .git directories, missing security.txt, and open redirects (all via stdlib urllib):
def quick_scan(url):
"""Run quick vulnerability checks"""
findings = []
# Check exposed .git
try:
r = urllib.request.urlopen(
urllib.request.Request(f'{url}/.git/config',
headers={'User-Agent': 'BB-Kit/1.0'}),
timeout=5
)
if r.status == 200:
body = r.read().decode('utf-8', errors='ignore').lower()
if 'repositoryformatversion' in body:
findings.append(f'EXPOSED: {url}/.git/config')
except:
pass
# Check security.txt
try:
r = urllib.request.urlopen(
urllib.request.Request(f'{url}/.well-known/security.txt',
headers={'User-Agent': 'BB-Kit/1.0'}),
timeout=5
)
if r.status == 200 and 'contact' in r.read().decode().lower():
findings.append(f'SECURITY.TXT: {url}/.well-known/security.txt')
except:
pass
return findings
The entire toolkit clocks in at ~280 lines — including the argument parser and error handling.
Design Philosophy
-
Stdlib only.
urllib.request,json,threading,argparse. That's it. If you have Python, you can run this. -
Fire-and-forget. No config files. No
.env. No API keys. The CLI is self-documenting. - Pi-friendly. The toolkit was built and tested on a Raspberry Pi 4. Memory footprint during recon: under 30MB.
-
Composable. Each command outputs clean text — pipe it into
nuclei, feed it toffuf, or chain it into your own scripts.
Real-World Usage
Here's a real workflow I run daily:
# 1. Enumerate subdomains for a bug bounty target
python3 bb_kit.py enum target.com > subs.txt
# 2. Probe which ones are live (parallel, 20 threads)
python3 bb_kit.py probe $(cat subs.txt) -t 20 > live.txt
# 3. Quick scan each live host for low-hanging vulns
while read line; do
url=$(echo "$line" | awk '{print $1}')
python3 bb_kit.py scan "$url"
done < live.txt
# 4. Feed live hosts into your favorite scanner
cat live.txt | awk '{print $1}' | httpx -silent | nuclei -t cves/
From zero to hunting in under 10 seconds.
Get the Toolkit
The full source is open source on GitHub:
👉 github.com/ulnit/bb-automation-kit
Free tier: 100 domains/day, all three commands.
Pro ($15 one-time): Unlimited domains, concurrent scanning, priority support.
If you find this useful, consider supporting the project — every contribution helps keep 23 AI products running 24/7 on a single Raspberry Pi:
Built with Python stdlib. Runs on a $35 Raspberry Pi. Zero excuses not to start hunting.
Top comments (0)