DEV Community

Cover image for I built an open-source web vulnerability scanner — here's what I learned about scan fatigue
Svetlin Minkov
Svetlin Minkov

Posted on

I built an open-source web vulnerability scanner — here's what I learned about scan fatigue

For the last few months I've been building BugBounty Arsenal — an open-source web application security scanner — mostly to scratch my own itch. I want to share the two problems that shaped it, because they're the parts I'm most proud of.

The problem with running a scanner

Anyone who has run a DAST tool on a schedule knows the failure mode: you scan every day, and every day it hands you the same 40 findings. After a week you stop reading the reports. The signal drowns in noise.

So the first thing I built wasn't a detector — it was a diff.

Scheduled scans in BBA don't notify you on every finding. Each run is compared against the previous completed run of the same schedule, keyed on a signature of title + detector + url + severity. You only get pinged on what's new:

  • New host exposed since yesterday? Alert.
  • Same misconfig you already triaged? Silence.

Triage state (confirmed / false-positive) also carries over between runs, so once you've dismissed something, it stays dismissed. That single change turned the scanner from "another dashboard I ignore" into something I actually read.

Making it fail a build

The second thing: a scanner is only useful in a pipeline if it can block a bad deploy.

There's a zero-dependency Python CLI (standard library only — no pip install) that starts a scan, waits for it, and exits non-zero when findings cross a severity threshold:

python bba_scan.py --target https://staging.example.com --category 1 --fail-on high
Enter fullscreen mode Exit fullscreen mode

Exit 0 = clean, 1 = threshold breached. Drop that into any CI and a regression in your attack surface blocks the merge.

It also exports SARIF, so findings land in GitHub's Security → Code scanning tab right next to CodeQL — with severity, rule and a link back:

- uses: FoxVR-sudo/BugBounty-Arsenal/.github/actions/bugbounty-scan@master
  with:
    api-key: ${{ secrets.BBA_API_KEY }}
    target: https://staging.example.com
    fail-on: high
Enter fullscreen mode Exit fullscreen mode

What's actually in it

  • 53 active + 10 passive detectors — XSS, SSRF, CORS, security headers, injection, exposed secrets, auth flaws…
  • Scheduled scans with the new-findings diff above
  • Attack surface management — tracks hosts / tech / ports across scans
  • Triage workflow — confirmed / false-positive, carried between runs
  • REST API + API keys, and an SSRF guard that blocks internal/infra targets by default

Stack: Django + DRF, Celery/Redis, PostgreSQL, React — the whole thing comes up with docker compose up.

Try it / self-host it

Only scan targets you own or are authorized to test.

I'd genuinely love feedback — especially on detector accuracy (false positives are the enemy) and what would make it fit into your workflow. What does your scan-fatigue look like?

Top comments (0)