Open-source project
arkadiyt/bounty-targets avatar
arkadiyt/bounty-targets

bounty-targets: an hourly mirror of bug bounty scopes, not a scanner

This project crawls bug bounty platform scopes (like Hackerone/Bugcrowd/Intigriti/etc) hourly and dumps them into the bounty-targets-data repo

735 stars135 forksRubyMIT

At a glance

What is it?
bounty-targets is a Ruby crawler that collects the public scope listings of several bug bounty platforms every hour and commits them to a separate data repository. It publishes lists of which assets are in scope and nothing more, so it belongs in a researcher's reconnaissance pipeline rather than in a testing toolchain.
Who is it for?
Use bounty-targets when you need a single normalised feed of in scope assets across several bug bounty platforms and are willing to pin a commit of the data repository for reproducibility. Do not treat it as a reconnaissance or testing tool, because it collects scope listings and does not scan, probe or validate anything.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 14 days ago.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

It collects scope, it does not test anything

The name suggests a tool that hunts for bugs. It is not one. The project description says it crawls bug bounty platform scopes hourly and dumps them into a separate repository, and the README says the same in plainer words: it crawls the Hackerone, Bugcrowd and other platform scopes and writes them out.

What lands in the output is a list of the assets each program considers fair game. Which assets those are, and the rules attached to them, is decided by the bounty platform and the program owner, not by this project. The crawler's job is to read that scope and republish it in one place.

That distinction matters more than it first appears. Scope is a legal and contractual boundary rather than a technical one, and the person best placed to interpret it is the program owner, not the aggregator. Reading a scope feed tells you which hosts a program has declared interesting. It tells you nothing about whether a host is vulnerable, whether it is still in scope today, or whether a bug you find there will be paid for.

So the useful audience is the researcher assembling a work list across several programs, and the engineer who needs to know what a program considers in range before starting a test.

Five platforms are supported and one is commented out

The README lists the platforms the crawler covers: Hackerone, Bugcrowd, Intigriti, YesWeHack and Federacy. Each of these also appears as a topic tag on the repository, which is a quick way to see the coverage from the project page.

One entry is deliberately switched off. Hackenproof appears in the list only inside an HTML comment, so it is not currently crawled even though the topic tag hackenproof is still attached to the repository. The difference between the visible list and the tags is a small but useful signal about how the project is maintained: the tag set outlives the enabled platforms, so a tag is not proof of coverage.

There is no equivalent for platforms that were never supported. If a program runs on a platform outside those five, it simply will not appear in the feed. For a researcher who works across several platforms, that is the practical limit of this project, and it is the first thing to check.

The crawler also does not distinguish between program types beyond what the platforms expose. Nothing in the README describes filtering by bounty tier, by eligibility, or by whether a program is currently accepting submissions, so any such filtering would have to happen downstream against the published data.

The output lands in a second repository, pushed over SSH

The architecture is deliberately split in two. This repository holds the crawler. The data goes to a separate repository, bounty-targets-data, whose address is the homepage of the project and which receives a commit every hour.

The publishing side is SSH based, and the installation instructions make that explicit. The destination is set through the GIT_HOST environment variable, and the README gives the value used for this project as the [email protected]:arkadiyt/bounty-targets-data.git SSH form. Alongside it, SSH_PRIV_KEY holds a private key authorised to write to that repository and SSH_PUB_KEY holds the matching public key. A fourth variable, SENTRY_DSN, is optional and takes a Sentry API key for exception tracking, so a failed crawl can be reported instead of silently producing nothing.

The hourly cadence is what makes the SSH write path important. A run that fails after the crawl but before the push leaves the data repository unchanged, which is the safe failure mode: consumers see the last good copy rather than a truncated one. The README does not describe what happens if the crawl succeeds and the push is rejected, so a consumer should not assume every commit in the data repository corresponds to a clean run.

Because the data lives in its own repository, it is consumed by pointing tools at that repository rather than at the crawler. That separation is what lets a researcher clone the data once and work offline.

Running it locally takes a clone, four variables and one script

The installation path in the README is short enough to reproduce. You clone the project, install the Ruby dependencies with bundle, set the environment variables, and execute the binary in the bin directory.

The four variables are the interesting part. SSH_PRIV_KEY and SSH_PUB_KEY are what authorise the push to the data repository, and GIT_HOST decides which repository receives it, defaulting in practice to the [email protected]:arkadiyt/bounty-targets-data.git address the README names. SENTRY_DSN is optional. Note that a local run is not read only: pointing it at a different GIT_HOST with your own key writes copies of the data to that repository, so a first run is best aimed at a repository you control.

The Ruby version is pinned by a .ruby-version file at the root, and the Gemfile and Gemfile.lock are both committed, so the dependency set for a given checkout is fixed rather than resolved at install time. The root also carries .rubocop.yml and a .rubocop_todo.yml for linting, and an .rspec file configuring the RSpec runner. The spec/ directory holds the test suite, and the GitHub Actions badge in the README title points at a build-test workflow, so the project does carry continuous test coverage.

For a one-off look, the more common route is to clone bounty-targets-data directly and read the JSON. The crawler itself is only needed if you want fresh scopes or your own destination repository.

Docker and Fly.io wrap the crawler in a scheduled container

The repository ships a container image and a Fly.io deployment path, which tells you how the hourly schedule is expected to run.

The Dockerfile starts from ruby:3.2, installs vim and cron with apt, and drops in the cronitor.io agent from a Linux amd64 tarball. It copies the Gemfile and Gemfile.lock before the rest of the source, runs bundle install, and then copies the project in, with a cron file copied to /etc/cron.d/cron.

dockerfile
FROM ruby:3.2
RUN apt update && apt-get install -y vim cron
WORKDIR /app
COPY Gemfile Gemfile.lock ./
RUN bundle install
COPY . .

The Makefile exposes the whole lifecycle, including a catch-all rule that funnels any target into a container.

bash
build:
	docker build . --tag bounty-targets
deploy:
	fly deploy
console:
	fly ssh console
%:
	$(MAKE) build
	docker run --rm -v $${PWD}:/app/ -it bounty-targets make -f Makefile.docker $@

Because the catch-all builds the image and then runs the requested target inside it with the working directory mounted at /app/, a developer can execute any Makefile.docker target without installing Ruby locally. The deploy target calls fly deploy against the fly.toml at the repository root, and the console target opens an SSH console on the running deployment, which is how you would inspect a crawler that is failing on the deployed instance rather than on your laptop.

Two details stand out. The image runs cron rather than a scheduled job platform, so the schedule is defined in the crontab file rather than in the deployment config. And the container image includes cron, the cronitor.io agent and vim, which is a working setup rather than a minimal image.

Why this is the wrong tool for the job next door

The limitations are structural, and they come from what the project is not.

There is no scanning, no probing, no asset discovery and no vulnerability testing anywhere in the description. If what you need is to know which of a program's declared assets actually resolve, which services they expose, or whether they are alive, this feed answers none of that. The data repository is a mirror of a decision made elsewhere.

The freshness model has a second consequence. Because the crawl runs hourly and commits each copy, the data repository accumulates one commit per crawl, so its history grows at the crawl cadence rather than at release cadence. A tool that reads the newest commit will see scopes that changed since you last looked, including assets that were removed from scope, which is a trap for anything that acts automatically on the list.

The platform coverage is also fixed at five providers with one disabled. Programs on other platforms never appear, and there is no documented mechanism for adding one beyond what the code in lib/ does.

Finally, there are no tagged releases of the crawler, so there is no version to pin for the code itself. The last push was on 2026-10-09 and the repository is not archived, so work is continuing, but pinning a crawl means pinning a commit of the data repository instead.

Mirror of five platforms versus the platform feed itself

The real alternative to this project is to consume each bounty platform directly and skip the mirror entirely. The difference is a trade of breadth for immediacy and authority.

Going to the platforms one by one means you read each program's own scope listing and its own rules, with the program owner's wording intact and the ability to see anything the aggregator does not model. You also learn about a scope change when it is published. The cost is that every platform has its own interface and its own way of expressing what counts as in scope, so a cross-programme work list means writing and maintaining that integration yourself for each provider, and any coverage gap in your own code is a gap in your results.

The mirror inverts that. One repository, one format, five providers, updated on a known cadence, which is exactly what you want when the question is which programmes include a given domain rather than what one programme's rules say. The price is the abstraction: normalised data, hourly delay, a fixed provider list, and a set of commits that tell you what changed without explaining it.

The project is licensed MIT, so reading, mirroring and modifying the crawler carries only the usual attribution obligation. The licence of the published data in the separate repository is not described in this README, and the two are separate artefacts, so a team redistributing the data should check the licence of bounty-targets-data itself rather than assume the crawler's licence covers it.

Editorial conclusion

Use bounty-targets when you need a single normalised feed of in scope assets across several bug bounty platforms and are willing to pin a commit of the data repository for reproducibility. Do not treat it as a reconnaissance or testing tool, because it collects scope listings and does not scan, probe or validate anything. Verify first by reading the scope list for your own program on the bounty-targets-data repository, and confirm the exact set of assets listed by the platform itself before you act on a line in that feed.

Frequently asked questions

How do I run bounty-targets locally?

Clone the project, install the dependencies with bundle, set the environment variables, and execute bin/bounty-targets. The variables are SSH_PRIV_KEY, SSH_PUB_KEY and GIT_HOST for writing to the destination repository, plus an optional SENTRY_DSN for exception tracking.

Which bug bounty platforms does bounty-targets cover?

The README lists Hackerone, Bugcrowd, Intigriti, YesWeHack and Federacy as supported. Hackenproof appears only in a commented out line, so it is not currently crawled even though the topic tag is still present on the repository.

Where does the collected scope data end up?

The crawler commits the collected scopes hourly into the separate bounty-targets-data repository. The destination is chosen with the GIT_HOST environment variable, and the push is authorised with the SSH_PRIV_KEY and SSH_PUB_KEY pair.

Official sources

  1. arkadiyt/bounty-targets on GitHub
  2. Issues
  3. License: MIT
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/arkadiyt-bounty-targets.svg)](https://hysenlabs.com/projects/arkadiyt-bounty-targets)

Was this useful?