Yotter: The 122-Star Bash Script That Chains Recon Like It's 2010 (And Why That Still Matters)
Hook
A single bash script with 122 GitHub stars performs reconnaissance faster than most junior penetration testers can configure their toolchain—no Python virtual environments, no Go binaries, just netcat and dirb.
Context
Reconnaissance automation hasn't fundamentally changed since the mid-2000s: enumerate subdomains, find live hosts, scan ports, bruteforce directories. What has changed is complexity. Modern frameworks like Amass, Nuclei, and Recon-ng offer sophisticated features—database persistence, API rate limiting, modular plugins, JSON output for pipeline integration—but they also demand installation overhead, configuration files, and mental models that slow down rapid iteration.
Yotter takes the opposite approach. Built as a monolithic bash script, it chains classic reconnaissance tools into a single linear workflow optimized for speed over sophistication. The entire dependency tree is netcat and dirb—tools pre-installed on most penetration testing distributions. This matters during Capture The Flag competitions where every minute counts, bug bounty initial triage when you're racing against other researchers, or internal assessments where you can't install custom tooling on client networks. Yotter represents a philosophical position: sometimes a 200-line shell script that runs immediately is more valuable than a 50,000-line framework that takes twenty minutes to configure.
Technical Insight
Yotter's architecture is deceptively simple: a sequential pipeline where each stage feeds the next, with minimal error handling and maximum throughput. The script begins by resolving the target domain to an IP address, then identifies the IP range to understand the infrastructure footprint. This range becomes the boundary for subsequent subdomain validation—a clever optimization that avoids wasting time on CDN addresses or third-party services.
The subdomain enumeration stage demonstrates bash's underutilized strength: parallel HTTP requests using background processes. Yotter queries three passive intelligence sources simultaneously—pkey.in, hackertarget.com, and virustotal.com—then merges results while an active brute-force loop runs in parallel:
# Passive enumeration (simplified from actual implementation)
for source in pkey hackertarget virustotal; do
curl -s "https://${source}.com/api?q=${domain}" |
grep -oE "([a-zA-Z0-9-]+\.)+${domain}" >> subdomains.tmp &
done
# Active brute-force runs concurrently
while read subdomain; do
(host "${subdomain}.${domain}" | grep "has address" &&
echo "${subdomain}.${domain}" >> subdomains.tmp) &
# Limit parallel jobs to avoid resource exhaustion
[[ $(jobs -r | wc -l) -gt 50 ]] && wait -n
done < wordlist.txt
wait # Ensure all background jobs complete
sort -u subdomains.tmp > subdomains_final.txt
This pattern—fire-and-forget background jobs with a semaphore-style job limit—achieves the reported ~250 checks/sec on commodity hardware without dropping into C or Go. The wait -n command (available in bash 4.3+) provides backpressure, preventing the script from spawning thousands of processes that would trigger OOM killers.
Port scanning follows a similar philosophy. Instead of invoking nmap with its overhead of OS fingerprinting and service detection, Yotter uses raw netcat in a tight loop targeting only HTTP/HTTPS ports (80, 443, 8080, 8443, 8000, and about 20 others). The implementation favors false positives over false negatives:
# Simplified port scanning logic
for ip in $(cat discovered_ips.txt); do
for port in 80 443 8080 8443 8000 8888 9090; do
(timeout 2 nc -zv "$ip" "$port" 2>&1 |
grep -q "succeeded" &&
echo "http://${ip}:${port}" >> http_targets.txt) &
[[ $(jobs -r | wc -l) -gt 100 ]] && wait -n
done
done
wait
The timeout 2 constraint prevents hanging on filtered ports, while nc -zv (zero I/O mode with verbose output) provides just enough information to identify open ports without full connection establishment. This achieves ~500 ports/sec because it avoids nmap's comprehensive service detection—a conscious trade-off prioritizing speed over accuracy.
The final stage invokes dirb with a custom wordlist focused on information leakage patterns: /server-status, /.git/config, /admin, /backup, /.env, and similar high-value targets. This isn't comprehensive directory enumeration; it's targeted exploitation of common misconfigurations. The wordlist contains roughly 200 paths compared to dirb's default 4,600+ entries, reducing scan time from hours to minutes.
What makes this architecture work is understanding bash's sweet spot. For I/O-bound operations (HTTP requests, network connections, DNS queries), bash's background job control provides embarrassingly parallel execution without threading complexity. The script never needs to parse complex data structures or perform CPU-intensive computation—it delegates those tasks to grep, sed, and external tools. The entire workflow stays in bash's wheelhouse: orchestrating external processes and manipulating text streams.
Gotcha
Yotter's linear architecture becomes a liability the moment something fails. There's no checkpoint system, no resume capability, no structured logging. If the script crashes during the port scanning phase after spending twenty minutes on subdomain enumeration, you start from scratch. The passive intelligence sources are hardcoded without fallback mechanisms—if pkey.in rate-limits your IP or hackertarget.com changes its API response format, those enumeration paths silently fail, and you won't notice until you analyze suspiciously sparse results.
The aggressive scanning approach makes Yotter unsuitable for anything requiring operational security. Every subdomain brute-force attempt, every port scan, every dirb request generates logs on target systems. Blue teams with basic monitoring will spot this activity immediately. There's no jitter in timing, no user-agent rotation, no request throttling—it's the reconnaissance equivalent of kicking down every door in a building while shouting. For red team engagements or assessments against mature security operations, this noise profile is disqualifying. Additionally, the hard dependency on external passive sources means you're leaking target information to third parties (pkey.in, hackertarget.com, virustotal.com), which violates most professional engagement scopes and bug bounty program rules that prohibit unauthorized information sharing.
Verdict
Use if: You need immediate reconnaissance results without installation overhead (CTF competitions, quick bug bounty triage, environments where you can't install custom tooling), you're assessing internal networks where stealth isn't required and you want a self-contained script that runs on any Linux system with netcat, or you're learning reconnaissance workflows and want readable bash code that demonstrates chaining enumeration techniques. Skip if: You need operational security and evasion capabilities for professional red team engagements, you're conducting large-scale assessments requiring result persistence, error recovery, and structured output for reporting, you need modern API integrations with services like Censys, Shodan, or SecurityTrails, or you require comprehensive coverage over speed—mature frameworks like Amass provide better passive source diversity and DNS resolution accuracy at the cost of setup complexity.