#!/usr/bin/env bash # Bug Bounty Workflow Helper # Manages the complete workflow from recon to report set -euo pipefail PROGRAM="${1:-}" DOMAIN="${2:-}" BB_ROOT="${HOME}/bug-bounty" TEMPLATE_DIR="${HOME}/.claude/context/business/security/bug-bounty" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color show_usage() { cat << EOF Bug Bounty Workflow Helper Usage: bb-workflow.sh [args] Commands: init Initialize directory structure for new program recon Run reconnaissance on program test Quick vulnerability test helper screenshot [type] Take annotated screenshot with border report Generate PDF report from JSON status Show program status and findings Examples: bb-workflow.sh init acme acme.com bb-workflow.sh recon acme bb-workflow.sh test acme http://localhost:3002 xss bb-workflow.sh screenshot acme vulnerability bb-workflow.sh report acme acme-xss-001 Directory Structure: ~/bug-bounty// ├── recon/ # Reconnaissance data ├── screenshots/ # Evidence screenshots ├── discoveries/ # Vulnerability JSON files └── reports/ # Generated PDF reports EOF } init_program() { local program="$1" local domain="$2" echo -e "${BLUE}[+] Initializing bug bounty program: $program${NC}" mkdir -p "$BB_ROOT/$program"/{recon,screenshots,discoveries,reports} # Create program info file cat > "$BB_ROOT/$program/info.txt" << EOF Program: $program Domain: $domain Started: $(date +%Y-%m-%d) Platform: [HackerOne/Bugcrowd/Other] Scope: [Add scope notes] Rules: - [Add important rules from program policy] Notes: - [Add your notes here] EOF # Create .gitignore cat > "$BB_ROOT/$program/.gitignore" << EOF # Sensitive bug bounty data screenshots/ discoveries/*.json reports/*.pdf recon/ # Keep directory structure !discoveries/.gitkeep !screenshots/.gitkeep !reports/.gitkeep !recon/.gitkeep EOF touch "$BB_ROOT/$program"/{discoveries,screenshots,reports,recon}/.gitkeep echo -e "${GREEN}[✓] Program initialized: $BB_ROOT/$program${NC}" echo -e "${YELLOW}[!] Edit info.txt with program details${NC}" } run_recon() { local program="$1" local program_dir="$BB_ROOT/$program" if [[ ! -d "$program_dir" ]]; then echo -e "${RED}[-] Program directory not found: $program_dir${NC}" echo -e "${YELLOW}[!] Run: bb-workflow.sh init $program ${NC}" exit 1 fi # Get domain from info.txt local domain=$(grep "^Domain:" "$program_dir/info.txt" | cut -d' ' -f2) if [[ -z "$domain" ]]; then echo -e "${RED}[-] Domain not found in info.txt${NC}" exit 1 fi echo -e "${BLUE}[+] Running reconnaissance on $domain${NC}" echo -e "${YELLOW}[!] This will take some time...${NC}" cd "$program_dir/recon" # Run your existing recon scripts if [[ -x "${HOME}/scripts/passive-recon" ]]; then echo -e "${BLUE}[+] Running passive recon...${NC}" "${HOME}/scripts/passive-recon" "$domain" fi if [[ -x "${HOME}/scripts/light-recon" ]]; then echo -e "${BLUE}[+] Running light recon...${NC}" "${HOME}/scripts/light-recon" "$domain" fi if [[ -x "${HOME}/scripts/bb-recon" ]]; then echo -e "${BLUE}[+] Running bug bounty recon (safe mode)...${NC}" "${HOME}/scripts/bb-recon" "https://$domain" fi echo -e "${GREEN}[✓] Reconnaissance complete!${NC}" echo -e "${YELLOW}[!] Review results in: $program_dir/recon/${NC}" # Generate manual testing guide if [[ -x "${HOME}/scripts/bb-report-generator" ]]; then echo -e "${BLUE}[+] Generating manual testing guide...${NC}" # Find the most recent bb-recon directory latest_recon=$(find . -maxdepth 1 -type d -name "bb-recon-*" -printf '%T@ %p\n' | sort -rn | head -1 | cut -d' ' -f2) if [[ -n "$latest_recon" ]]; then "${HOME}/scripts/bb-report-generator" "$latest_recon" echo -e "${GREEN}[✓] Manual testing guide created!${NC}" echo -e "${CYAN}[*] Read: $latest_recon/manual-testing-guide.md${NC}" fi fi } quick_test() { local program="$1" local url="$2" local type="$3" echo -e "${BLUE}[+] Quick vulnerability test: $type${NC}" "${HOME}/scripts/quick-vuln-test.sh" "$url" "$type" } take_screenshot() { local program="$1" local type="${2:-evidence}" if [[ ! -d "$BB_ROOT/$program" ]]; then echo -e "${RED}[-] Program directory not found: $program${NC}" exit 1 fi "${HOME}/scripts/bb-screenshot-annotate.sh" "$program" "$type" } generate_report() { local program="$1" local vuln_id="$2" local program_dir="$BB_ROOT/$program" local json_file="$program_dir/discoveries/${vuln_id}.json" local pdf_file="$program_dir/reports/${vuln_id}.pdf" if [[ ! -f "$json_file" ]]; then echo -e "${RED}[-] JSON file not found: $json_file${NC}" exit 1 fi echo -e "${BLUE}[+] Generating PDF report...${NC}" cd "$TEMPLATE_DIR" bun run latex/generate.ts "$json_file" "$pdf_file" if [[ -f "$pdf_file" ]]; then echo -e "${GREEN}[✓] Report generated: $pdf_file${NC}" echo -e "${YELLOW}[!] Review before submitting!${NC}" # Open PDF (if on desktop with xdg-open) if command -v xdg-open &> /dev/null; then xdg-open "$pdf_file" & fi else echo -e "${RED}[-] Report generation failed${NC}" exit 1 fi } show_status() { local program="$1" local program_dir="$BB_ROOT/$program" if [[ ! -d "$program_dir" ]]; then echo -e "${RED}[-] Program not found: $program${NC}" exit 1 fi echo -e "${BLUE}=== Bug Bounty Program Status ===${NC}" echo "" cat "$program_dir/info.txt" echo "" echo -e "${BLUE}=== Findings ===${NC}" local findings=$(find "$program_dir/discoveries" -name "*.json" -not -name ".gitkeep" | wc -l) local reports=$(find "$program_dir/reports" -name "*.pdf" | wc -l) echo "Total findings: $findings" echo "Generated reports: $reports" if [[ $findings -gt 0 ]]; then echo "" echo "Discoveries:" ls -1 "$program_dir/discoveries/"*.json 2>/dev/null | xargs -n1 basename || true fi } # Main command router case "${1:-}" in init) [[ -z "${2:-}" ]] || [[ -z "${3:-}" ]] && show_usage && exit 1 init_program "$2" "$3" ;; recon) [[ -z "${2:-}" ]] && show_usage && exit 1 run_recon "$2" ;; test) [[ -z "${2:-}" ]] || [[ -z "${3:-}" ]] || [[ -z "${4:-}" ]] && show_usage && exit 1 quick_test "$2" "$3" "$4" ;; screenshot|ss) [[ -z "${2:-}" ]] && show_usage && exit 1 take_screenshot "$2" "${3:-evidence}" ;; report) [[ -z "${2:-}" ]] || [[ -z "${3:-}" ]] && show_usage && exit 1 generate_report "$2" "$3" ;; status) [[ -z "${2:-}" ]] && show_usage && exit 1 show_status "$2" ;; *) show_usage exit 1 ;; esac