Skip to content

Back to the catalog

BountySkiller
github.comrepo

BountySkiller

BountySkiller is a Flask app with two bug-bounty-focused tools: a collector that pulls disclosed HackerOne hacktivity and bug-bounty writeups (plus RSS/Google sources) into local JSON, and "Hunt Buddy," a browser-driven orchestrator that takes a target profile, runs a gap analysis against a set of pluggable bug-class hunting modules (sourced from an external HUNT_TOOLS directory, e.g. SSRF), and produces ranked findings with per-module status and enforced scope.domains restrictions. It exposes a small REST API (/api/hunt/plan, /api/hunt/run, /api/fetch, etc.) for scripting the collection and hunt workflow.

TL;DR A Flask tool that scrapes disclosed HackerOne/bug-bounty writeups and drives a scoped, module-based automated bug-hunt orchestrator ("Hunt Buddy") with gap analysis and ranked findings.
Document

What it is

BountySkiller is a self-hosted Flask app (python app.py, serves on http://127.0.0.1:5000) with two independent tools: a writeup/hacktivity collector (/) and the Hunt Buddy orchestrator (/hunt). The summary states the concept; what follows is the operational detail an engineer needs to actually run it and to trust its output.

How it works

Hunt Buddy plans before it acts. A plan table lists every bug-class module, whether it can run, and the exact profile key missing if it cannot. A skipped module is never reported as clean — absence of a finding is not evidence of safety. The engines live outside this repo, at the directory pointed to by HUNT_TOOLS (defaults to ~/Bounty/claude-bug-bounty/tools).

Scope is enforced by the engines, not the UI: scope.domains is required, and an out-of-scope request is blocked before the socket opens. The /hunt page refuses to start without a scope.

What to do

Run with the tools directory set explicitly:

HUNT_TOOLS=~/Bounty/claude-bug-bounty/tools python3 app.py
open http://127.0.0.1:5000/hunt

Collector API:

  • POST /api/hunt/plan — profile JSON in body, returns gap analysis, sends no traffic (safe dry inspection)
  • POST /api/hunt/run — body {"profile": {...}, "only": ["ssrf"], "dry_run": false}
  • GET /api/hunt/status, GET /api/hunt/report

Google Custom Search is optional and free-tier limited to 100 queries/day:

export GOOGLE_API_KEY=...
export GOOGLE_CSE_ID=...

(or pass google_api_key / google_cse_id as query params).

Caveats

The page states several failure modes that will silently corrupt results if unknown:

  • The HackerOne index field is team_handle, not team.handle — the latter silently returns 0 hits.
  • RSS sources only expose recent posts, so months=24 returns the same rows as months=1 for them.
  • bounty is often null (HackerOne only exposes disclosed amounts), and min_bounty drops all null-bounty rows — a high threshold discards most data.
  • HackerOne pages are rate-limited to 0.4s apart; don't hammer.
flowchart TD
    P[POST /api/hunt/plan] -->|no traffic| PLAN[Module gap analysis]
    PLAN --> D{Module runnable?}
    D -->|missing profile key| SKIP[Skipped — NOT reported clean]
    D -->|scope.domains present| RUN[POST /api/hunt/run]
    RUN --> B{Request in scope?}
    B -->|out of scope| BLOCK[Blocked before socket opens]
    B -->|in scope| ENGINE[HUNT_TOOLS engine executes]

Technologies named here