Maillart et al.
Discovery probability falls as t^-0.40 after launch, so
an old program is not automatically a bad one, but a new one
genuinely is easier to enter.
Most bug bounty lists rank by reward size and freshness. honeybe ranks by whether a program actually pays, how crowded it is, and whether its scope fits the skills you really have. Every step below is arithmetic, published, and reproducible from the JSON this site serves.
The largest prize on a page is not the prize most hunters can win. In a survey of 159 bug bounty hunters, saturation ranked 10th and program age 13th among the factors they actually weigh, while poor responsiveness and payout disputes were the two biggest problems they reported (Akgul et al., arXiv:2301.04781). So the score leads with whether a program responds and pays, then how crowded it is, and only then how large its rewards are.
Discovery probability falls as t^-0.40 after launch, so
an old program is not automatically a bad one, but a new one
genuinely is easier to enter.
In a survey of 159 hunters, responsiveness and payout disputes beat prize size as the reasons hunters leave a program.
arXiv:2301.04781Across 9,942 HackerOne reports, higher reputation won the better outcome in 59.85% of near-identical pairs. Reputation is a tiebreaker we cannot see fairly, so honeybe does not model it at all.
arXiv:2511.18608Only HackerOne programs that offer bounties and are open to submissions. At the last crawl that is 221 programs. Every other program, including unpaid HackerOne VDPs, Bugcrowd, Intigriti, YesWeHack and direct programs, appears in the Catalog and is never scored.
| Signal | HackerOne field | Used for |
|---|---|---|
| Age | launched_at | novelty decay |
| Reports in 90 days | reports_received_last_90_days | crowding |
| Resolved total | resolved_report_count | slop pressure |
| Response efficiency | response_efficiency_percentage | payout reliability, triage |
| Response status | response_efficiency_indicator | triage, penalties |
| Lifetime paid | formatted_total_bounties_paid_amount | context |
| Paid in 90 days | formatted_bounties_paid_last_90_days | payout reliability |
| Last resolved | last_report_resolved_at | recency |
| Average bounty | average_bounty_lower/upper_amount | value per competition |
| Scope size | structured_scopes.total_count | crowding denominator, breadth |
novelty = (age_months + 1) ^ -0.40
crowding = (reports_90d / 3) / max(scope_count, 1)
inverse_crowd = 1 / (1 + crowding ^ 1.2)
payout_reliability = 0.5 * (efficiency / 100)
+ 0.3 * (paid_90d > 0)
+ 0.2 * exp(-days_since_resolved / 90)
value_per_comp = min(1, log1p(avg_bounty) / log1p(20000)) / (1 + crowding)
triage_quality = (efficiency / 100) * {1.0 ok, 0.75 missed, 0.5 failed}
scope_breadth = min(1, log1p(scope_count) / log1p(500))
base = 100 * (0.22 novelty + 0.22 inverse_crowd + 0.22 payout_reliability
+ 0.16 value_per_comp + 0.11 triage_quality + 0.07 scope_breadth)
score = clamp(base + penalties, 0, 100)
| Condition | Points |
|---|---|
| Response indicator failed | -25 |
| Response indicator missed | -10 |
| More than 1,000 reports in 90 days | -20 |
| More than 3,000 reports in 90 days | -10 |
| Nothing resolved in 180 days | -15 |
| Slop risk at or above 0.6 | -10 |
| Will they pay | Condition |
|---|---|
| Pays reliably | indicator ok, efficiency at or above 80, paid in 90 days, resolved in 30 days |
| Pays slowly | enough signal, but slower than the bar above |
| Missed targets | indicator missed, so the program is blowing its own stated SLAs |
| Risky | indicator failed, efficiency below 50, or dormant more than 180 days |
| Unknown | not enough signal. Shown honestly, not scored favorably |
Your profile changes the order, never the facts. Four rules keep it
honest, and public/engine.test.js asserts each one.
| Rule | Effect |
|---|---|
| Experience level | scales every self-rating: beginner x0.5, intermediate x0.85, advanced x1.0 |
| Profile strength | personal weight = 15% x completeness, so a half-filled profile applies half-strength |
| Bounded influence | a personal score moves at most plus or minus 12 points from the population score |
| Skill gap | simulates learning a weak surface to 3/5 and counts the programs that would enter your top 50 |
Surface mismatch is share-weighted over the two largest surfaces: an effective rating at or below 1 costs 18 points times its share, a rating of 2 costs 8. Tools amplify a surface you already practice and can never create skill from zero. Short sessions discount very large scopes.
The Catalog is the honest answer to a simple question: what else is out
there, and what do we actually know about it? It merges four open
sources: the arkadiyt mirrors for HackerOne, Bugcrowd, Intigriti and
YesWeHack, plus the lissy93 lists for platform and direct programs. Rows
are deduplicated on platform:slug and merged, so a program
listed twice keeps the better field from each source.
Figure 4. Catalog rows by source and the fields each row can prove.
points = 45 * bounty_known
+ 30 * min(1, log1p(scope_count) / log1p(400))
+ 15 * min(1, scope_types / 6)
+ 10 * disclosure_terms
+ 10 * min(1, log1p(max_payout) / log1p(1000000))
order = 100 * points / sum(weights of known fields)
Points are normalised over the fields that exist, so a missing payout figure neither helps nor hurts. Every row prints a coverage percentage over four checks: bounty status, payout, scope and disclosure terms. The Catalog also tracks when honeybe first saw each program, which is what powers the "Latest additions" ordering. That date means first seen by us, not the program's launch date, and it is labelled that way.
node public/engine.test.js. They assert bounds,
monotonicity, cold start and the beginner guard.
pipeline/score.py and
pipeline/badges.py. There is no model, no ranking service
and no hidden tiebreaker.
localStorage.