Skip to main content

Secret scanner for the AI coding era — catches leaked API keys before they ship.

Project description

keyburn

Secret scanner built for the AI coding era.

Cursor, Copilot, and Lovable write code fast. Sometimes too fast — hardcoded API keys, database URLs, and JWT secrets end up committed before anyone notices. Keyburn catches them before they ship.

  • 57 detection patterns — AWS, OpenAI, Anthropic, Stripe, Supabase, GitHub, Slack, and more
  • Shannon entropy analysis — catches secrets that don't match a known pattern
  • Actionable remediation hints — tells you exactly how to fix each finding, not just that something's wrong
  • Framework-aware — knows that NEXT_PUBLIC_SECRET_KEY is exposed to the browser, that Supabase service_role keys bypass RLS, etc.
  • Zero noise escape hatches# keyburn:ignore, allowlists, baselines, per-path excludes
  • CI-native — text/JSON/SARIF output, GitHub code scanning integration, fail threshold per severity

Install

pip install keyburn
# or, zero-install:
pipx run keyburn scan .

Quickstart

# Scan current directory
keyburn scan .

# Scan and fail CI on any high-severity finding
keyburn scan . --fail-on high

# Only scan files changed in this PR
keyburn scan . --diff origin/main

# Only scan staged files (pre-commit)
keyburn scan . --pre-commit

# Output SARIF for GitHub code scanning
keyburn scan . --format sarif --out keyburn.sarif

Verify likely-live keys

keyburn verify checks whether a detected token is still active for selected providers.

Supported providers (current): openai, github, stripe.

# safest path: load from env var (avoid shell history leaks)
keyburn verify --from-env OPENAI_API_KEY --provider openai

# auto-infer provider from token format
keyburn verify --from-env GITHUB_TOKEN --provider auto

# fail CI if token appears active
keyburn verify --from-env STRIPE_SECRET_KEY --provider stripe --fail-on-valid

GitHub Action

Add this to any workflow — it scans on every push/PR and uploads findings to GitHub code scanning:

- name: Scan for secrets
  uses: safouanb/keyburn@v0

Or with options:

- name: Scan for secrets
  uses: safouanb/keyburn@v0
  with:
    fail_on: high          # low | medium | high (default: high)
    format: sarif          # text | json | sarif (default: sarif)
    upload_sarif: "true"   # upload to GitHub code scanning (default: true)
    comment_pr: "true"     # sticky PR comment summary (default: false)

Full workflow example:

name: Secret scan

on: [push, pull_request]

jobs:
  secrets:
    runs-on: ubuntu-latest
    permissions:
      security-events: write  # required for SARIF upload
      pull-requests: write    # required if comment_pr=true
    steps:
      - uses: actions/checkout@v4
      - uses: safouanb/keyburn@v0
        with:
          fail_on: high
          comment_pr: "true"

Pre-commit hook

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/safouanb/keyburn
    rev: v0.1.5
    hooks:
      - id: keyburn

Or use the CLI directly in a git hook:

# .git/hooks/pre-commit
#!/bin/sh
keyburn scan . --pre-commit --fail-on high

Suppressing false positives

Inline, for a single line:

EXAMPLE_KEY = "not_a_real_secret_for_docs"  # keyburn:ignore

Allowlist by regex in keyburn.toml:

[allowlist]
regex = [
  "^sk_test_",        # all Stripe test keys
  "^EXAMPLE_KEY_",   # placeholder values in docs
]

Baseline — accept current state, catch new ones:

# Run once to write the baseline
keyburn scan . --baseline baseline.json --update-baseline

# Future scans only alert on NEW findings
keyburn scan . --baseline baseline.json --fail-on high

Skip files or directories:

[scan]
exclude_paths = ["tests/fixtures/**", "docs/examples/**"]
exclude_dirs  = [".venv", "node_modules"]

Disable specific rules:

[scan]
disable_rules = ["stripe-secret-test", "entropy"]

Configuration (keyburn.toml)

Drop a keyburn.toml in your repo root (see keyburn.toml.example):

[scan]
max_file_size_bytes = 2097152
exclude_dirs        = [".venv", "node_modules", "dist"]
exclude_paths       = ["tests/fixtures/**"]
disable_rules       = []
respect_gitignore   = true   # skip files in .gitignore (default: true)

[allowlist]
regex = []

What it detects

Category Providers
AI APIs OpenAI, Anthropic, Groq, HuggingFace, Replicate, Cohere
Cloud AWS (key + secret + session), GCP, Firebase
Payments Stripe (live + test + restricted)
Auth GitHub PATs (classic + fine-grained), OAuth tokens, Clerk, Auth0
Comms Slack (tokens + webhooks), Twilio, SendGrid, Mailgun, Discord, Telegram
Database PostgreSQL, MySQL, MongoDB, Redis (connection strings)
Infra Heroku, Vercel, Netlify, Doppler, Sentry
E-commerce Shopify
Packages npm, PyPI tokens
Framework NEXT_PUBLIC_ secrets, Supabase service role vs anon key
Generic Hardcoded passwords, JWT secrets, PEM keys, .env pasted into source
Entropy High-entropy strings assigned to secret-looking variables

Output formats

Text (default) — rich panels with remediation hints per finding:

╭─ HIGH  Stripe Secret Key (live) ────────────────────────────────╮
│   File: src/payments.js:12:20                                    │
│   Rule: stripe-secret-live                                       │
│   Match: sk_l****************************1234                    │
│                                                                  │
│   How to fix: This is a LIVE Stripe key — it can charge real     │
│   cards. Roll it immediately at dashboard.stripe.com/apikeys.    │
│   Use STRIPE_SECRET_KEY env var instead.                         │
╰──────────────────────────────────────────────────────────────────╯

JSON — machine-readable with full finding metadata:

keyburn scan . --format json | jq '.summary'

SARIF — GitHub code scanning compatible:

keyburn scan . --format sarif --out keyburn.sarif

Git history scanning

Scan the last N commits for secrets that were added then "deleted":

keyburn scan --history 50    # last 50 commits
keyburn scan --history all   # full history (slow on large repos)

Precision benchmark

Track scanner noise over time against real OSS repositories:

python scripts/benchmark_precision.py

Results are written to:

  • benchmarks/results/latest.json
  • benchmarks/results/latest.md

CI can run this weekly via .github/workflows/precision-benchmark.yml.

Adoption loop

Track external adoption/noise metrics across real open-source repositories:

python scripts/adoption_loop.py

Results are written to:

  • adoption/results/latest.json
  • adoption/results/latest.md

CI can run this weekly via .github/workflows/adoption-loop.yml.

Known limitations

  • Key verification currently supports only OpenAI, GitHub, and Stripe.
  • Verification is a live HTTP check and can return unknown during rate limits/outages.
  • A valid check means "accepted by provider now"; it does not measure scope or blast radius.
  • .gitignore matching is intentionally lightweight and may differ from full git pathspec semantics.

Open-core

The scanner and all detection rules are open-source (Apache-2.0). Dashboards, Slack/email alerting, and one-click credential rotation live in a separate hosted product.

Contributing

See CONTRIBUTING.md. New detectors: open an issue with the provider, a redacted example, expected severity, and known false positives.

License

Apache-2.0. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

keyburn-0.1.5.tar.gz (37.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

keyburn-0.1.5-py3-none-any.whl (31.3 kB view details)

Uploaded Python 3

File details

Details for the file keyburn-0.1.5.tar.gz.

File metadata

  • Download URL: keyburn-0.1.5.tar.gz
  • Upload date:
  • Size: 37.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for keyburn-0.1.5.tar.gz
Algorithm Hash digest
SHA256 0cbe3cfd50b7aed0497f136f674b87f39e26f07a88ddc85c850be23b27e84ac0
MD5 1af6d063c0f18ebb68ef4e06eb4bafda
BLAKE2b-256 a8e6a6ae6b85e80edf238ec3f58d5d7e2f420b1558c6b87df59e21fbfe4127de

See more details on using hashes here.

Provenance

The following attestation bundles were made for keyburn-0.1.5.tar.gz:

Publisher: release.yml on safouanb/keyburn

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file keyburn-0.1.5-py3-none-any.whl.

File metadata

  • Download URL: keyburn-0.1.5-py3-none-any.whl
  • Upload date:
  • Size: 31.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for keyburn-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 f22b785f796927ef5fa15ce4f29e4d04cd7012fca2001a94636a6064221055be
MD5 f4547f7b2c6de7a0650017289656d81f
BLAKE2b-256 e663851cd1fa5d799dac486cb5b6f660de23b7c613a712ad53224daf72072f1d

See more details on using hashes here.

Provenance

The following attestation bundles were made for keyburn-0.1.5-py3-none-any.whl:

Publisher: release.yml on safouanb/keyburn

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page