← back to gallery

Bounty Slop Watch

Which bug-bounty programs are still alive in the AI-slop era — HackerOne + Bugcrowd, scraped nightly.

dev-toolssecuritybug-bountyhackeronebugcrowdai-policyscraperrss
Open product ↗

bounty-slop-watch

A public health board for bug-bounty programs in the AI-slop era. Independent
security researchers and OSS maintainers can see which HackerOne / Bugcrowd
programs are still paying, which paused intake, and which explicitly banned
AI-generated reports — before they spend a week writing a report nobody will read.

The site nightly scrapes the public HackerOne and Bugcrowd directories,
classifies each program with a small keyword-rule engine, and surfaces:

Each program has an embeddable SVG badge (/badge/:platform/:handle.svg) and an
RSS feed (/feed.xml) so the data flows out of the site.

Data sources (real, public, polled at runtime — no mocks)

| Source | URL pattern | Refresh | Notes |
| --- | --- | --- | --- |
| HackerOne public program directory | https://hackerone.com/programs/search?query=type%3Ahackerone&sort=published_at%3Adescending&page=N | nightly, 03:17 UTC | returns paginated JSON with name, url, stripped_policy, meta.submission_state |
| Bugcrowd public engagements | https://bugcrowd.com/engagements.json?category=bug_bounty&page=N | nightly, 03:42 UTC | returns paginated JSON with name, briefUrl, rewardSummary, accessStatus |
| HackerOne per-program detail | https://hackerone.com/{handle} | every 15 min, max 30/run, only detail_stale=1 rows | scrapes <meta og:description> to enrich policy text |

All requests send User-Agent: bounty-slop-watch/1.0 (+https://holyai.me/bounty-slop-watch) and respect a 1 req/s per-host rate limit. If a source fails the scrape run is logged to scrape_runs with the error; existing data is not wiped.

On first boot the server detects an empty DB and runs the two directory scrapes immediately (about 30 seconds total) before scheduling the nightly cron jobs.

Classifier

Pure keyword rules (deterministic, cheap, in classifier.js). Order of precedence:

  1. program closed, discontinued the program, ended the program, … → closed
  2. program paused, not accepting reports, intake closed, … → paused
  3. AI mention (e.g. ai-generated, llm-generated, chatgpt, used ai) + a ban verb (prohibit, reject, ban, forbid, not accept) → ai_banned / ai_policy=banned
  4. AI mention + a restrict verb (must disclose, require human, limit) → ai_policy=restricted
  5. Disappeared from directory for ≥2 consecutive runs → closed + disappeared event
  6. Default → active / ai_policy=allowed

Bugcrowd accessStatus and HackerOne submission_state override status when the platform itself says the program is paused/closed.

HTTP endpoints (all under /bounty-slop-watch)

| Method | Path | Returns |
| --- | --- | --- |
| GET | /health | {ok:true} |
| GET | / | SPA shell |
| GET | /program/:platform/:handle | SPA shell (deep-link) |
| GET | /badge/:platform/:handle.svg | SVG badge — color by status |
| GET | /feed.xml | RSS 2.0 of last 50 program events |
| GET | /feed.xml?program=hackerone/curl | RSS scoped to one program |
| GET | /api/summary | counts by status, total, last successful scrape |
| GET | /api/programs?status=&platform=&q=&limit=&offset= | filterable list |
| GET | /api/programs/healthiest?limit=20 | top active by bounty ceiling |
| GET | /api/casualties?days=30 | recent negative transitions |
| GET | /api/restrictions | programs with restricted/banned AI policy |
| GET | /api/program/:platform/:handle | full record + last 20 events |
| GET | /api/events?limit=50&kind= | raw event stream |
| GET | /api/scrape-runs?limit=20 | scraper transparency |

No POST/PUT/DELETE. No auth. CORS open on /api/* and badge so the SVG embeds cleanly.

Storage

SQLite (better-sqlite3, WAL) at data/bounty-slop-watch.db. Three tables:
programs, program_events, scrape_runs. Schema lives in db.js.

Embeddable badge

![bounty-slop-watch](https://holyai.me/bounty-slop-watch/badge/hackerone/curl.svg)

Color: green=active, yellow=restricted, orange=paused, red=closed/ai_banned, gray=unknown.

Run locally

npm install
PORT=4877 node server.js

First boot kicks off the two directory scrapes and populates the DB in ~30 s. Then the cron schedule takes over (nightly).

What this product is not