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 added lines changed in this PR
keyburn scan . --diff origin/main

# Only scan added lines in 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.6
    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.6.tar.gz (38.2 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.6-py3-none-any.whl (32.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: keyburn-0.1.6.tar.gz
  • Upload date:
  • Size: 38.2 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.6.tar.gz
Algorithm Hash digest
SHA256 4db2057b23af2b976e1fd0ca2d787dd7ac81513278ed3146fe7e6f2c1f4a3325
MD5 751dc28445d23707d1d32d2807ee29b0
BLAKE2b-256 ecf78ce38d5576fd8276006c2a9b4268ebc99d3ebca18a4ef398b1a47a776bc0

See more details on using hashes here.

Provenance

The following attestation bundles were made for keyburn-0.1.6.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.6-py3-none-any.whl.

File metadata

  • Download URL: keyburn-0.1.6-py3-none-any.whl
  • Upload date:
  • Size: 32.1 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.6-py3-none-any.whl
Algorithm Hash digest
SHA256 b5f2d279eac0c8f4146c42b155b340e6a6e13a092e81caf00358bc28d803f942
MD5 e3da3cf255247f5e6966d080c8a7e187
BLAKE2b-256 4cd8aa5790c0316cafc3eb708b650d6edda738ad5e1f7a45d6e4be12ad921209

See more details on using hashes here.

Provenance

The following attestation bundles were made for keyburn-0.1.6-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