leakkill
Leaked a key? Find it, see if it's live, and kill it in one command. Free, local, zero dependencies.
Free tools are great at finding secrets. What happens after a leak is usually left to paid platforms: is this key still working, whose account is it, how do I revoke it right now, and how do I clean it out of git history? leakkill does that part too, from your terminal, for free.
$ leakkill verify
#1 LIVE GitHub token ghp_************ config.py:3
octocat scopes: repo, workflow
#2 DEAD AWS access key AKIA************ deploy/old.sh:12
key id is unknown or deactivated
#3 UNVERIFIABLE Credentials in URL postgres://app:****@db.prod.internal .env.backup:1
3 unique secret(s), 1 LIVE.
$ leakkill revoke --only 1 --yes
#1 GitHub token: REVOKED (HTTP 202)
Install
pip install leakkill
Python 3.9+, no dependencies. Latest development version:
pip install git+https://github.com/ayushanand27/leakkill
Commands
| Command | What it does | Network? |
|---|---|---|
leakkill [scan] [PATH ...] |
Find secrets. Exit code 1 if any. | Never |
leakkill verify |
Also check each secret against the provider that issued it: live or dead, which account, which scopes | Read-only "who am I" calls |
leakkill revoke |
Show what can be revoked. With --yes, revoke the live ones (--only 1,3 to pick) |
Only with --yes |
leakkill report |
Write leakkill-report.md: every leak, its status and owner, and the cleanup steps in order |
Same as verify (--no-verify to skip) |
leakkill install-hook |
Git pre-commit hook that blocks commits containing secrets | Never |
leakkill install-claude-hook |
Stop Claude Code reading .env and keys or writing secrets into code |
Never |
Every scan command also accepts --staged (pre-commit), --history (every commit on every branch,
including secrets you already "deleted"), --exclude-tests and --json.
What it can verify and revoke
| Provider | Verify (live? whose?) | Revoke from the CLI |
|---|---|---|
GitHub (ghp_, github_pat_, gho_, ghu_, ghr_) |
✅ user and scopes | ✅ via GitHub's credential revocation API (the owner is notified) |
GitLab (glpat-) |
✅ token name, scopes, expiry | ✅ self-revoke |
Slack tokens (xox…) |
✅ user and workspace | ✅ auth.revoke |
| Discord webhooks | ✅ server and channel | ✅ deletes the webhook |
| AWS access key and secret | ✅ IAM ARN and account (STS, needs no permissions) | ⚠️ deactivates the key if it has iam:UpdateAccessKey, otherwise console steps |
SendGrid (SG.) |
✅ scopes | ✅ the key deletes itself if it has API-key permissions |
| Stripe (live and test keys), OpenAI, Anthropic, OpenRouter, Groq, Hugging Face, Replicate, DigitalOcean, npm, Telegram, Slack webhooks | ✅ (account or username where the API returns it) | ❌ the provider has no API for it, so you get the exact page or command |
| Google API keys, Shopify, PyPI, Docker Hub, Twilio, Postman, Perplexity, Linear, Azure Storage, private keys, JWTs, credentials in URLs, generic high-entropy secrets | detected, not verified | step-by-step rotation guidance |
How it compares
| leakkill | Gitleaks | TruffleHog OSS | GitGuardian | GitHub Secret Protection | |
|---|---|---|---|---|---|
| Price | Free (MIT) | Free (MIT) | Free (AGPL) | Free for individuals, roughly $15–30/dev/month for teams | Free on public repos, $19/committer/month on private |
| Runs fully local | ✅ | ✅ | ✅ | ❌ SaaS | ❌ GitHub only |
| Detectors | 31 | 150+ | 800+ | 550+ | provider list |
| Checks if a key is live | ✅ 17 providers | ❌ | ✅ (its main strength) | ✅ | ✅ some |
| Revokes from the CLI | ✅ 6 providers | ❌ | ❌ (Enterprise) | partial | ❌ |
| Incident report and history-purge steps | ✅ Markdown file | ❌ | ❌ | ✅ dashboard and playbooks | ❌ |
| Guards AI coding agents | ✅ Claude Code hooks | ❌ | ❌ | ❌ | ❌ |
| Dependencies | none | Go binary | Go binary | CLI + account | GitHub |
Detector and pricing figures come from public sources in October 2026. Use what fits your needs: if breadth of detection matters most, run Gitleaks or TruffleHog alongside leakkill.
Tested with real credentials
End to end on Windows with real, throwaway credentials:
| Credential | verify |
revoke --yes |
verify again |
|---|---|---|---|
| GitHub token | LIVE, correct user | REVOKED (HTTP 202) | DEAD |
| Discord webhook | LIVE, correct server and channel | REVOKED (HTTP 204) | DEAD |
| Slack bot token | LIVE, correct bot and workspace | REVOKED | DEAD (the app was uninstalled, as Slack documents) |
| Slack webhook | LIVE | (died with the app) | DEAD |
| Stripe test key | LIVE, correct account, "test mode" | manual roll in dashboard | |
| Hugging Face token | LIVE, correct user and token role | manual delete |
Against the real AWS, GitLab, Anthropic and npm APIs, invalid keys are correctly reported DEAD. Providers not yet tested with a live key (OpenAI, OpenRouter, Groq, Replicate, DigitalOcean, SendGrid, Telegram) are covered by tests using simulated API responses.
Benchmark (reproducible, run October 2026)
Noise on clean, popular repos (unique secrets reported, default settings):
| Repo | leakkill | Gitleaks 8.28 |
|---|---|---|
| psf/requests | 1 (private-key test fixtures) | 4 (same fixtures, one per file) |
| pallets/flask | 2 (docs example SECRET_KEYs) |
2 (same) |
| django/django | 1 (a CSRF test fixture) | 8 |
| expressjs/express | 0 | 0 |
Recall on 17 planted realistic secrets: leakkill 17/17, Gitleaks 14/17. Gitleaks missed a Postgres URL with a password, a Discord webhook and a Telegram bot token. The planted set was written by us, so it is biased toward formats we support. Gitleaks detects many formats we don't.
Safety model
scannever touches the network.- A secret is only ever sent to the provider that issued it. Hosts are hard-coded, and HTTP redirects are never followed, so a credential can't be bounced to another server (this is tested).
- Verification uses read-only identity calls: GitHub
GET /user, Slackauth.test, AWSGetCallerIdentityand so on. revokeis a dry run unless you pass--yes, and only touches keys that verified as live.- Raw secrets are never printed or written to the report. The only exception is the opt-in
report --replacements FILE(needed bygit filter-repo), which is created with permissions 600.
Cleaning git history
leakkill revoke --history --yes # 1. kill live keys first: history rewrites don't help once copied
pip install git-filter-repo
leakkill report --history --replacements .leakkill-replacements.txt
git filter-repo --replace-text .leakkill-replacements.txt
rm .leakkill-replacements.txt
git push --force --all && git push --force --tags # every collaborator must re-clone
AI coding agent guard (Claude Code)
leakkill install-claude-hook adds hooks to .claude/settings.json that block:
- prompts that contain secrets (before they reach the model)
- reading
.env,*.pem,id_rsa,.npmrcand similar, whether through the Read tool or any shell command that names such a file (cat,grep,base64,python -c,cp…)..env.exampleis allowed. - writing hard-coded keys into code (writing them into
.envis allowed)
This was tested live with the Claude Code CLI: prompts with keys, Read .env, cat .env,
grep . .env and writing an AWS key into app.py were all blocked. The check is pattern-based: a
command that builds the file name at runtime can get past it. Pair it with OS-level permissions for
hard guarantees.
Use in CI (GitHub Action)
- uses: actions/checkout@v4
- uses: ayushanand27/leakkill@v0
The build fails if a secret is found, and the incident report appears in the job summary. Options:
- uses: ayushanand27/leakkill@v0
with:
path: . # files or directories to scan
exclude-tests: true # skip test_* files and tests/ dirs
history: true # scan every commit (needs `fetch-depth: 0` on checkout)
verify: true # check secrets with their providers; fail only if one is LIVE
The action exposes found (the number of unique secrets) as an output. Outside GitHub Actions, use
pip install leakkill && leakkill scan ..
Use with the pre-commit framework
# .pre-commit-config.yaml
repos:
- repo: https://github.com/ayushanand27/leakkill
rev: v0.3.0
hooks:
- id: leakkill
Or without the framework: leakkill install-hook.
Suppressing false positives
- Add
leakkill:ignoreon a line. - List paths or globs in
.leakkillignore(for examplefixtures/or*.snap). - High-entropy matches ignore placeholders (
your_key,example,${VAR}), variables named test/example/fake/mock, password hashes and values without digits.
Known limitations
- Fewer detectors than Gitleaks or TruffleHog.
- Verification behind a proxy that injects its own credentials (some corporate and sandbox proxies
do) can report the proxy's identity. Run
verifyfrom a normal network. - AWS keys can only be verified when the secret key is found too (any file in the scan).
- Stripe, OpenAI, Anthropic, npm and Telegram offer no revoke API, so those need a manual click.
MIT licensed.
Metadata
Release files for leakkill 0.4.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| leakkill-0.4.2.tar.gz | 32.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| leakkill-0.4.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 57.4 kB
Release files / leakkill-0.4.2.tar.gz
| Download URL | leakkill-0.4.2.tar.gz |
|---|---|
| Size | 32.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c7295109472f100e691b1eabe0a48115bee50ec67bae2a870cebfe96f51d75ac
|
|
BLAKE2b-256 checksum How to use checksums |
593361f5048d3a0556db425dc6eef618f85b4c022d4e3c34706745e47ad64d47
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.
Transparency logRelease files / leakkill-0.4.2-py3-none-any.whl
| Download URL | leakkill-0.4.2-py3-none-any.whl |
|---|---|
| Size | 24.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8e5774f5364cda71db2465f34d8eb3a1614b85f6729d3b407d759a0d61e80eb7
|
|
BLAKE2b-256 checksum How to use checksums |
23f3db984076cd06bb98d4f2f3866c0ad14935accc74f980fbb6ca5592d9002a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.
Transparency log