leakferret
Context-aware secret scanner that lets an AI agent scan code, verify which leaked keys are actually live by calling the provider, and rewrite them to env-var lookups before committing. Exposes scan/verify/rewrite tools plus secret-type and verifier resources over MCP.
README
<p align="center"> <img src="brand/logo.png" alt="leakferret" width="440"> </p>
<p align="center"> <a href="https://github.com/leakferrethq/leakferret/actions/workflows/ci.yml"><img src="https://github.com/leakferrethq/leakferret/actions/workflows/ci.yml/badge.svg" alt="CI"></a> <a href="LICENSE.txt"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License: MIT"></a> <a href="https://marketplace.visualstudio.com/items?itemName=leakferret.leakferret"><img src="https://img.shields.io/badge/VS%20Code-Marketplace-007ACC?logo=visualstudiocode&logoColor=white" alt="VS Code Marketplace"></a> <a href="https://lobehub.com/mcp/leakferrethq-leakferret"><img src="https://lobehub.com/badge/mcp/leakferrethq-leakferret" alt="MCP Badge"></a> </p>
MCP-native secret scanner — verified findings, agent-applied rewrites.
leakferret is one fast Rust binary that is engine, CLI, and MCP server. It finds hardcoded secrets in your code, calls the provider to confirm which ones are actually live, and rewrites the leak in place to read from an environment variable. It runs in your terminal, in CI, and as a tool your coding agent calls before it commits — and the raw secret never leaves your machine.
<p align="center"> <img src="brand/demo.gif" alt="leakferret finds a leaked AWS key, verifies it, and rewrites it to ENV.fetch" width="760"> </p>
What it looks like
Say you accidentally commit a real key, plus the usual noise:
# .env — every key below is fabricated for this example
STRIPE_SECRET_KEY=sk_live_FAKE_example_not_a_real_key # fabricated
GITHUB_TOKEN=ghp_FAKE_example_not_a_real_token # fabricated
SENDGRID_API_KEY=${SENDGRID_API_KEY} # a reference — not a leak
ADMIN_PASSWORD=changeme # a placeholder — not a leak
AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE # AWS's public docs example
leakferret verify calls each provider and tells you what is real and live —
and stays quiet on the rest:
$ leakferret verify .
.env
L2 UNKNOWN CRITICAL stripe_secret sk_l..._key
L3 VERIFIED CRITICAL github_token ghp_...oken ← live, rotate it now
2 findings · 1 verified · 1 unknown
<sub>The keys above are fabricated, so the VERIFIED line illustrates what a
genuinely live key reports — on these examples both would be UNKNOWN.</sub>
The ${SENDGRID_API_KEY} reference, the changeme placeholder, and the
well-known AKIAIOSFODNN7EXAMPLE example are recognized and left out — that
precision is the point. Then leakferret rewrite --apply rewrites the
hardcoded key in your code (it leaves .env files alone — there's nothing
sensible to rewrite a secret to there):
# app/billing.rb (fabricated example)
- Stripe.api_key = "sk_live_FAKE_example_not_a_real_key" # fabricated
+ Stripe.api_key = ENV.fetch("STRIPE_API_KEY")
…and appends STRIPE_API_KEY= to .env.example with a seed command for your
secret manager. Find → confirm live → fix, with almost no false alarms.
The full secret value never leaves your machine. Only a redacted
AKIA...4XYZpreview is ever written to a report, log, or network message.
Quick start
Install however you like — every package ships the same prebuilt binary.
# Ruby gem
gem install leakferret
# npm (CLI)
npm i -g @leakferret/cli
# Go
go install github.com/leakferrethq/leakferret-go/cmd/leakferret@latest
# Native binary — download from GitHub Releases, unpack, and put it on $PATH:
# https://github.com/leakferrethq/leakferret/releases
# Rust, from source
cargo install leakferret-cli
Then scan the current directory:
leakferret scan .
scan respects .gitignore and also reads dotfiles such as .env. Add
--git to walk commit history instead of the working tree.
Every wrapper honors a
LEAKFERRET_BINenvironment variable pointing at a local binary, for offline or development use.
How it works
leakferret runs findings through a five-station pipeline. Each station only sees what it needs, and the raw secret never advances past disk.
- Scan — a fast regex pre-filter over your files, across 60+ secret
types. Respects
.gitignore, reads dotfiles like.env, and (with--git) walks history. - Catalog — every candidate is checked against a signed database of
known-public example credentials: Stripe test keys,
AKIAIOSFODNN7EXAMPLE, jwt.io samples, RFC examples. Matches are marked FIXTURE so documented examples never raise a false alarm. The catalog is bundled with the binary and can be refreshed and signature-verified. - Classify — each remaining candidate gets a verdict: REAL, FIXTURE, or UNKNOWN. This runs offline by default (path rules plus dummy-marker heuristics), or asks the host editor or agent's own language model — no extra API key, no added cost.
- Verify — makes a single harmless API call to the provider to confirm a key is LIVE. Around 25 providers are covered natively (AWS SigV4, GitHub, GitLab, Stripe, OpenAI, Anthropic, Slack, Twilio, SendGrid, Mailgun, Datadog, Heroku, npm, PyPI, DigitalOcean, Hugging Face, Groq, Replicate, Notion, Postman, Figma, Linear, Square, Shopify, Databricks), with a trufflehog binary fallback for the rest. The call goes straight from your machine to the provider — leakferret has no servers.
- Rewrite — swaps a hardcoded literal for an environment-variable lookup
(
ENV.fetch/os.environ/process.env), appends a line to.env.example, and prints seed commands for your secret manager (env, Vault, Doppler, AWS Secrets Manager, or Infisical).
A baseline stores one-way HMAC fingerprints of known findings — never the raw secret — so CI can fail only on new leaks.
Use it with AI agents (MCP)
MCP (Model Context Protocol) is the open standard for giving coding agents tools. Agents hardcode secrets too, and nobody reviews their diffs line by line — leakferret lets the agent self-check before it commits.
Start the server over JSON-RPC on stdio:
npx @leakferret/mcp
Add it to your mcpServers config (Claude Desktop, Cursor, Continue,
Claude Code):
{
"mcpServers": {
"leakferret": {
"command": "npx",
"args": ["@leakferret/mcp"]
}
}
}
For Claude Code, save that block as .mcp.json in your project root, or add
it with one command:
claude mcp add leakferret -- npx -y @leakferret/mcp
If you installed the native binary, you can point at it directly instead:
{
"mcpServers": {
"leakferret": {
"command": "leakferret",
"args": ["mcp"]
}
}
}
leakferret is also listed in the MCP Registry
as io.github.leakferrethq/leakferret, so registry-aware clients can discover it.
Tools exposed: scan_repository, classify_candidates, verify_finding,
propose_rewrite, and baseline_diff. A classify prompt is also provided so
an agent can classify candidates inline using the model it already has. Two
read-only resources expose the engine's catalog as context: leakferret://secret-types
(every detectable pattern) and leakferret://verifiers (the live-verification providers).
How it compares
| gitleaks | trufflehog | detect-secrets | GitGuardian | leakferret | |
|---|---|---|---|---|---|
| Live provider verification | — | ✓ | — | ✓ | ✓ |
| In-place env-var rewrite | — | — | — | — | ✓ |
| MCP server for AI agents | — | — | — | — | ✓ |
| Baseline (fail only on new) | — | — | ✓ | ✓ | ✓ |
| SARIF / Code Scanning | ✓ | ✓ | — | ✓ | ✓ |
| Free, local, no account | ✓ | ✓ | ✓ | — | ✓ |
gitleaks is the fastest pre-commit regex blocker. trufflehog set the bar for live verification. detect-secrets owns the baseline-a-legacy-repo workflow. GitGuardian is the paid platform with the broadest detectors and a dashboard. leakferret does the regex pre-filter, verifies which keys are live, rewrites the leak to an env var, and runs as an MCP server so coding agents check their own diffs. Full writeup: leakferret.com/compare.
CLI reference
leakferret scan Regex pre-filter only (no classifier, no verifier)
leakferret verify Scan + classify + provider verification
leakferret rewrite Scan + classify + propose/apply ENV-fetch rewrites
leakferret org Scan every public repo owned by a GitHub user/org
leakferret baseline Manage the per-repo fingerprint baseline
leakferret catalog Load and inspect the fixture catalog
leakferret mcp Start the MCP server on stdio
Scan a whole GitHub account or org in one go (handy for finding leaks across all your public repos before someone else does):
leakferret org leakferrethq # all public repos for that owner
leakferret org myco --token "$GITHUB_TOKEN" --format sarif > leaks.sarif
Common flags:
# scan
leakferret scan . # working tree
leakferret scan . --git # scan HEAD's commit history
leakferret scan . --git --all # scan every branch / tag
leakferret scan . --git --since HEAD~50 # bounded history window
# verify
leakferret verify . # best-effort verification
leakferret verify . --verify-mode none --fail-on any # offline gate: exit 1 on any finding
leakferret verify . --only-verified # emit only confirmed-live keys
leakferret verify . --verify-mode ever-verified # fail on historical leaks
leakferret verify . --verifier-timeout-secs 10
# rewrite
leakferret rewrite . --apply # write ENV.fetch in place
leakferret rewrite . --dry-run-diff # show the diff, touch nothing
leakferret rewrite . --check # CI mode: exit 1 if rewrites pending
leakferret rewrite . --apply --include-unknown # also fix UNKNOWN (unconfirmed) candidates
leakferret rewrite . --backend doppler # seed cmds for your manager
# baseline (scan/verify are read-only — they never write to your repo)
leakferret baseline init # create .leakferret-baseline.json (gitignores the salt)
leakferret verify . --update-baseline # record current findings into the baseline
leakferret baseline show
leakferret baseline ignore --fingerprint <fp> # acknowledge a finding
# catalog
leakferret catalog info
leakferret catalog test "sk_test_4eC39..." # deterministic FIXTURE verdict
leakferret catalog refresh # fetch + signature-verify update
Shared flags on scan / verify / rewrite: --format, --show-fixtures,
--exclude <glob>, --only <path>, --only-verified,
--fail-on <none|any|real|verified>.
--backend accepts env, vault, doppler, aws-secrets-manager,
infisical.
Block commits locally (pre-commit hook)
Catch a secret before it is ever committed. From your repo root:
cat > .git/hooks/pre-commit <<'HOOK'
#!/bin/sh
# Offline secret scan (no network). Blocks the commit on any finding.
leakferret verify . --verify-mode none --fail-on any || {
echo "leakferret blocked this commit. Bypass: git commit --no-verify"
exit 1
}
HOOK
chmod +x .git/hooks/pre-commit
--verify-mode none keeps it fully offline; --fail-on any exits non-zero on
any non-fixture finding (documented examples like AKIAIOSFODNN7EXAMPLE are
still ignored). Pair it with leakferret baseline init so the hook only blocks
on new secrets. To share the hook with a team, commit it to .githooks/ and
run git config core.hooksPath .githooks once.
The hook runs on any git client — the terminal, GitHub Desktop, the VS Code Source Control panel, JetBrains, and so on — because they all run git's pre-commit hook. A blocked commit shows the leakferret output in that client's "commit failed" dialog.
A pre-commit hook is a local convenience, not a wall. Anyone — or any AI
agent — can skip it with git commit --no-verify, and git offers no way to
forbid that locally. So treat the hook as fast feedback, and make the
GitHub Action (or the same
leakferret verify step in your CI) the enforcing gate: it runs
server-side on every push and pull request, where --no-verify can't reach it.
Output formats
Choose with --format:
- pretty — colored terminal output (default).
- json — structured findings for scripting and pipelines.
- sarif — for GitHub Code Scanning. The GitHub Action wrapper
(
leakferrethq/leakferret-action@v1) uploads it for you.
Privacy guarantee
This is the trust story, and a dedicated test enforces it:
The full secret value lives only on disk. It is never written into any report, log, network message, or model prompt. Only a redacted first-4 + last-4 preview (for example
AKIA...4XYZ) ever leaves the process.
Verification sends the key straight from your machine to the provider. leakferret has no servers and collects nothing. Baselines store one-way HMAC fingerprints, never the raw secret.
One operational caveat about verify. Verification makes a real,
authenticated request per candidate, so it lands in the key owner's own audit
log — an AWS STS GetCallerIdentity shows up in CloudTrail, a GitHub token
check shows up as token use, and so on. Point verify only at repositories
whose secrets are yours to test; running it against someone else's code means
authenticating into their accounts and leaving traces there. To scan with no
network calls at all, use leakferret scan instead of verify, or pass
--verify-mode none.
How it compares
- gitleaks is a fast regex scanner. leakferret matches that pre-filter and adds provider verification, so you act on live keys instead of triaging regex noise.
- trufflehog verifies secrets against providers. leakferret matches that too — and adds the MCP/agent layer and the agent-applied rewrite that neither competitor has. The signed fixture catalog also keeps known-public example keys from being reported as live.
Platforms
Prebuilt binaries for v0.1.6:
x86_64-unknown-linux-gnux86_64-apple-darwinaarch64-apple-darwinx86_64-pc-windows-msvcaarch64-pc-windows-msvc
Verifying the binaries
Every release tarball is signed with Sigstore /
cosign — keyless, via GitHub OIDC — and ships a matching *.cosign.bundle. You
can prove a download was built by this repository's release workflow and was
never tampered with:
cosign verify-blob \
--bundle leakferret-0.1.6-x86_64-unknown-linux-gnu.tar.gz.cosign.bundle \
--certificate-identity-regexp 'https://github.com/leakferrethq/leakferret/.*' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
leakferret-0.1.6-x86_64-unknown-linux-gnu.tar.gz
Each tarball also ships a .sha256 for a basic integrity check.
Links
- Website: https://leakferret.com
- Source: https://github.com/leakferrethq/leakferret
- Catalog data: https://github.com/leakferrethq/leakferret-catalog
- Wrappers: ruby · go · npm · action · vscode
- Maintainer: Maria Khan <missusk@protonmail.com>
License
MIT for the engine, CLI, MCP server, and all language wrappers. CC-BY-SA-4.0 for the fixture catalog data.
trufflehog is an optional,
user-installed AGPL-3.0 tool that leakferret invokes as a separate process for
fallback verification. It is not bundled, modified, or redistributed. See
NOTICE.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.