# Autonomous Bug-Bounty Pipeline

> Catches a silent scope change within 15 minutes and starts the deep audit with no human in the loop.
>
> https://pravda.systems/work/bug-bounty-hunting · 2026-06-13

**Problem.** Public bug-bounty programs reward the first to report, so a quiet scope change is missed by anyone auditing by hand across multiple platforms.

**Solution.** An always-on watchdog catches the change in 15 minutes, alerts across five channels, and launches AI workers that audit the code and draft findings unattended.

**Outcome.** First live run drove 55 hypotheses to closure and produced 3 triaged findings (one Medium, two Low), including 634 USDC.e stranded in a deployed contract.

## Key metrics

- **4** Platforms monitored — Cantina, Code4rena, Sherlock, HackerOne, one source adapter each, polled every 15 minutes _(verified: watchdog/sources/ directory: cantina.py, code4rena.py, sherlock.py, hackerone.py)_
- **5** Alert channels — ntfy, Telegram, email, GitHub issue, Twilio voice, fire in parallel and escalate until acknowledged _(verified: watchdog/notify.py fan_out() function, docs/CHANNELS.md)_
- **55** Hypotheses closed on first engagement — Each struck with quoted-code rationale or confirmed by a passing Foundry proof-of-concept _(verified: programs/<engagement>/STATUS.md: 'Strike count: 55 of 55 closed (50 struck + 5 submitted)')_
- **3** Findings triaged on platform — One Medium and two Low severity, all received triage scores on Cantina _(verified: programs/<engagement>/STATUS.md: 'Cantina triage RECEIVED 2026-04-23 on 3 of the 3 actually-submitted findings')_
- **6.2k** Python lines of code — Pipeline source across watchdog/, orchestrator/, and tests/, built and tested in two days _(verified: stats.json entry bug-bounty-hunting loc_by_ext_top .py: 6247)_

## Outcome

**First live engagement: 55 hypotheses closed, 3 findings triaged on the platform.** The pipeline ran end-to-end on a public Cantina program covering four Solidity contract suites. Every hypothesis was either struck with quoted-code rationale or confirmed with a passing Foundry proof-of-concept on a local blockchain fork. Three findings were submitted and received triage scores: one Medium and two Low severity. One Low finding pinned **634 USDC.e stranded** in a deployed contract.

## What it does

**Watches four bounty platforms and starts the deep audit the moment scope changes, with no human in the loop until findings exist.** Public bug-bounty programs run on a first-to-report model. A scope change quietly added to a live program is worth more than racing the field on a fresh launch, but catching it within minutes and immediately running a deep adversarial audit requires infrastructure that does not exist off-the-shelf.

The watchdog polls Cantina, Code4rena, Sherlock, and HackerOne using their public APIs. For each program it computes a scope hash over asset names, reward tiers, and rules, so a silently-added contract fires a `SCOPE CHANGED` event even when the platform makes no announcement. On a trigger it fans alerts across **5 channels** in parallel: ntfy push, Telegram, email (SMTP), GitHub issue (which doubles as the acknowledgment channel), and a Twilio voice call that re-dials every **15 minutes** until the operator closes the issue.

The orchestrator receives the event, renders a structured workspace (scope, known-issues pulled from prior audit PDFs, attack-surface checklist), creates one git worktree per checklist block so workers never share a checkout, then spawns one supervisor per worker. Each supervisor runs `claude -p` in headless stream-JSON mode, scans output for completion claims, idle timeouts, API usage limits, and any attempt to submit, and responds appropriately: nag the worker back to the next unchecked item, sleep to the quota reset time and resume the same session, or flag a submission attempt loudly for the operator.

## Why it is faster than a human

**It runs the work no person can keep up with: nine attack surfaces audited in parallel, hundreds of hypotheses tracked at once.** The checklist driving each worker covers nine blocks: reentrancy and callback surfaces, signature replay, arithmetic and accounting invariants, oracle trust, access-control archaeology, deployment archaeology (bytecode-vs-source diffs and silent-fix analysis across git tags), cross-contract emergent behavior, invariant fuzzing, and web/app scope.

Each worker owns exactly one block in its own isolated copy of the code. Workers append every hypothesis and verdict to a live `STATUS.md`, and that file is how the supervisor measures progress between nags. The overseer tracks all worker processes, restarts any that crash, and writes a `SWARM_STATUS.md` each pass so the operator has a single dashboard for the entire swarm.

## How the operator stays in control

**Nothing reaches a platform without a human clicking submit, and every proof-of-concept runs on a safe local copy of the chain.** A worker that attempts to reach a submission endpoint is flagged with a `.SUBMISSION-ATTEMPT-*` marker and the operator is notified immediately. The operator gets a phone call that re-dials until acknowledged, reviews the drafted findings in the workspace, and decides what to submit.

The test suite enforces this guarantee with no network calls: `httpx.MockTransport` for all HTTP, a scripted `_fake_claude.py` shim that emits programmed stream-JSON output for supervisor testing, and throwaway SQLite databases under `tmp_path`. Zero API spend, zero network calls. The full pipeline runs offline before any real engagement.

## Speed of delivery

**The whole pipeline was built and tested in two days, 19 commits, then a live engagement.** 6.2k lines of Python across `watchdog/`, `orchestrator/`, and `tests/`. Adding a new platform requires writing exactly one file (a source adapter implementing a single `fetch()` method) and touching nothing else in the poll loop, notify fan-out, or worker scaffold.

## Features

- **Scope-change detection** — Hashes every program's assets, reward tiers, and rules, so a quietly-added in-scope contract fires an alert even with no platform announcement.
- **Five-channel alert escalation** — A trigger fires ntfy, Telegram, email, a GitHub issue, and a Twilio voice call in parallel, re-dialing until the operator acknowledges.
- **Worker swarm with per-block ownership** — Each AI worker owns one attack surface in its own git worktree, so parallel workers can never overwrite each other's work.
- **Supervisor nag loop** — Streams each worker's output to nudge stalls back on task, sleep through API usage limits and resume the same session, and flag any submission attempt.
- **Structured audit workspace** — Every engagement gets a generated workspace: scope, a live hypothesis tracker, known issues pulled from prior audit PDFs, and proof-of-concept and findings folders.

## Architecture

Two packages: `watchdog/` (poll loop, source adapters, SQLite state, multi-channel notify) and `orchestrator/` (scaffold, overseer, per-worker supervisor). Each source adapter implements one interface method, so adding a platform touches only one file. The poll loop, notify fan-out, scaffold, and worker swarm are platform-agnostic.

- **watchdog/poll.py** — Main poll loop: iterates all source adapters, diffs against SQLite state, fires notify and launch on events. Supports --seed (silent first-run ingest), --loop (daemon), --dry-run.
- **watchdog/sources/** — One file per platform: cantina.py, code4rena.py, sherlock.py, hackerone.py. Each implements Source.fetch() returning a normalized Program list. ETag-conditional requests, exponential backoff on 429/503.
- **watchdog/state.py** — SQLite-backed state: seen programs keyed by (source, id), scope hashes, alert records with escalation timestamps, ETag cache.
- **watchdog/notify.py** — fan_out() fires all configured channels in parallel (best-effort, so one failure never blocks others). escalate() re-calls Twilio and checks GitHub issue closed-state each poll pass.
- **orchestrator/launch.py** — On-event scaffold: resolves scope repos, renders workspace templates, creates per-worker git worktrees, spawns the overseer detached.
- **orchestrator/overseer.py** — Supervisor-of-supervisors: partitions checklist into blocks, ensures K worktrees, spawns one supervisor process per block, monitors and restarts crashed supervisors, writes SWARM_STATUS.md each pass.
- **orchestrator/supervisor.py** — Per-worker nag loop: runs claude -p in stream-JSON mode, scans output for completion/idle/quota/submission signals, resumes or nags the worker forward, logs cost.log, writes .SWEEP-* and .SUBMISSION-ATTEMPT-* markers.
- **templates/program/** — Jinja2 cookiecutter for a new programs/<slug>/ workspace: SCOPE.md, STATUS.md, CLAUDE.md, KNOWN_ISSUES.md, checklist.md (9 attack-surface blocks).

## Tech

- **Languages:** Python
- **Frameworks:** pytest, httpx, Jinja2, Foundry (Solidity PoCs)
- **Infrastructure:** SQLite, GitHub Actions, Windows Task Scheduler, Twilio, Telegram Bot API, ntfy
- **AI/ML:** Claude (claude -p headless, Max subscription), Claude Code (orchestration and development)

## Skills demonstrated

- AI agent orchestration at scale
- Multi-agent swarm design with parallel isolation
- Autonomous monitoring and alerting pipelines
- Integrating multiple third-party platform APIs
- Multi-channel escalating notifications
- Crash-safe state management (SQLite)
- Smart-contract security tooling (Solidity, Foundry)
- Offline-testable systems (mock transports, fake process shims)
- Git worktree-based parallel isolation
