Skip to main content
Glama

secretscan-mcp

Let your AI agent find secrets you committed by mistake, in your files and in your git history, without the secrets ever reaching the agent.

What's different here. Other secret-scanning MCP servers either call a vendor's cloud API (GitGuardian's ggmcp), only look at the working tree (mcp-secret-sentinel), or are generic scanners. secretscan-mcp is offline (one dependency, mcp; it shells out to your own git), it walks git history and tells you which commit added and removed each secret, it ends with a provider-specific rotation and clean-up checklist, and its safety claim is structural and tested: no code path can return a raw secret, and a test launches the server over stdio and checks that no planted secret, or 16-character slice of one, appears in any tool output or error.

It finds API keys, tokens, private keys, passwords in URLs and .env mistakes, in the working tree and in every commit you let it walk. Then it tells the agent what to do: rotate first, look for misuse, clean up, and (optionally, as text only) how to rewrite history.

Companion to the tutorial secretscan-mcp-the-hard-way, which builds a minimal version of this server from scratch.

What it looks like

Real output (the secrets are fake values generated by the test suite):

> scan_tree("C:\code\demo")
Scanned 2 files (git repository: .gitignore respected; skipped 0 binary, 0 over 1 MB). 2 finding(s).

HIGH   f-15ab4258b891b540  aws-access-key-id          .env:1  AKIA... (20 chars)
HIGH   f-b5d779ed381cbf95  github-token               app/settings.py:2  ghp_... (40 chars)

> scan_history("C:\code\demo")
Scanned 3 commit(s). 3 distinct secret(s) found: 1 removed from the files but STILL IN HISTORY, 2 still present in the newest scanned commit.

REMOVED HIGH   f-8d09a993cf035308  stripe-live-key            old.py:1  sk_l... (36 chars)
        added in d98048147385 (2026-11-06), removed in 8996cdd170d6 (2026-11-06)
PRESENT HIGH   f-15ab4258b891b540  aws-access-key-id          .env:1  AKIA... (20 chars)
        added in e7274b88dc45 (2026-11-06)

> explain_finding("f-8d09a993cf035308")
Stripe live secret or restricted key (stripe-live-key, severity high)
How to rotate / revoke:
  1. Dashboard > Developers > API keys > the key's menu > Roll key. Choose an expiry for the old key ...
Rewriting history does not un-leak a secret. Once a commit was pushed, assume it was copied ...

Related MCP server: secrets-leak-audit-mcp

Install

You need Python 3.10+ and git on your PATH.

Claude Code

claude mcp add secretscan -- uvx secretscan-mcp

Claude Desktop (add to claude_desktop_config.json)

{
  "mcpServers": {
    "secretscan": {
      "command": "uvx",
      "args": ["secretscan-mcp"]
    }
  }
}

Or with pip: pip install secretscan-mcp, then run secretscan-mcp.

Try asking

  • "Scan C:\code\myapp for committed secrets."

  • "Has anything secret ever been committed to this repo, even if it was deleted later?"

  • "Is my .env file ignored and untracked?"

  • "I leaked a GitHub token in an old commit. What exactly do I do?"

  • "Give me a remediation checklist for this repo, in order."

  • "Show me what I'd put in .secretscan-ignore to accept the current findings."

Tools

Tool

What it does

scan_tree(path)

Scan the files git add . would pick up (tracked plus untracked-not-ignored), so .gitignore is respected. Skips binaries, files over 1 MB, lockfiles, vendored directories; never follows symlinks.

scan_history(path, max_commits=500, all_branches=False)

Stream git log -p, report each distinct secret once with the commit that added it and the one that removed it. REMOVED = gone from the files, still in history. Says when older commits were not scanned.

check_gitignore(path)

Are .env, *.pem, *.key, id_rsa, credentials.json, *.tfvars ... ignored and untracked? Reports tracked ones (with git rm --cached as text), untracked-but-not-ignored ones, and ignore-rule gaps.

explain_finding(id)

What the credential is, step-by-step rotation at the provider (AWS, GitHub, GitLab, Slack, Stripe, Google, Anthropic, OpenAI, npm, PyPI, SendGrid, JWT, URL passwords, private keys), how to check for misuse, and why history rewriting does not un-leak it.

suggest_remediation(path)

Scans tree and history and returns an ordered checklist: rotate, check for misuse, remove from the tree, optionally rewrite history (git filter-repo and BFG commands as text only), prevent recurrence.

make_baseline(path)

The lines to put in .secretscan-ignore to accept current findings (fingerprints only). It does not write the file.

What it detects

AWS access key IDs and secret keys; GitHub (classic and fine-grained), GitLab, Slack (tokens and webhooks), Stripe (live and test), Google API, Anthropic, OpenAI, npm, PyPI and SendGrid keys; JWTs (the header must decode as JSON); PEM private key blocks; passwords embedded in URLs; and generic assignments such as API_TOKEN = "..." that pass entropy, character-class, length and placeholder filters.

False-positive control is part of the design: hashes, UUIDs, base64 images, lorem ipsum, os.environ[...] and ${VAR} references, password: str, changeme-style placeholders, lockfile integrity hashes and identifier-like values are all in the test corpus and must produce zero findings.

The ignore file (baseline)

<repo root>/.secretscan-ignore holds one fingerprint per line, # starts a comment:

f-b5d779ed381cbf95  # test token in the docs, already revoked

A fingerprint is a 16-hex-character SHA-256 prefix of the rule and the value. It identifies a finding without containing it. A line that is not a fingerprint is an error, and the error never echoes the line, in case someone pasted a raw secret.

Security

  • Findings are always redacted. A finding is: type, file, line, commit, fingerprint, and the value as first 4 characters plus length. Secrets shorter than 16 characters show no characters at all. For provider tokens the 4 characters are the non-secret type marker (AKIA, ghp_).

  • No tool returns a raw secret. Finding has no field that can hold one; the raw value exists only inside the detector, long enough to compute the fingerprint and the preview. The source line is never printed.

  • A last line of defence. Every tool result and every error message is re-checked against the high-confidence rules. If anything matches (for example, a file named like a token), the tool refuses to return it. Error messages never echo user input that could be a secret (unknown ids, ignore-file lines).

  • Read-only. The server never writes a file, makes no network connection, and runs only git ls-files, git log, git check-ignore and git rev-parse, as argument lists (never a shell). core.fsmonitor is switched off and --no-ext-diff --no-textconv are used, so scanning an untrusted clone does not run its code.

  • Remediation is text. git filter-repo and BFG commands are printed for you to run. History rewriting needs the secret text, and the server will not print it, so the replacements file is yours to fill in.

  • Fingerprints are truncated hashes of the value. For high-entropy tokens that is safe to share. A weak, guessable password could in principle be confirmed by hashing guesses, so do not publish the ignore file for repos that hold such values.

  • The honest limit: a leak is a leak. Removing a secret from history does not make it safe. Rotate it.

Limits

  • Pattern-based. No finding does not prove there are no secrets; a finding is not proof of a live credential (nothing is verified against the provider, because that needs the network).

  • Generic detection needs a digit in the value and, for non-password names, 16+ characters. Pass-phrases made of words only, and short passwords under a non-password name, are not detected. UUID-valued secrets are skipped by design.

  • Lockfiles, minified files, images, node_modules, vendor, .venv and files over 1 MB are skipped, in the tree and in history.

  • History status (PRESENT/REMOVED) is tracked per distinct value across the scanned window; a value moved between files within one commit counts as unchanged. Only the newest max_commits are walked.

  • .gitignore is applied through git, so a directory that is not a repository is scanned without it (the output says so).

Tests

pip install ".[test]" "ruff==0.16.0" "mypy==2.3.0"
ruff check src tests && mypy --strict src
pytest tests

The tests build real git repositories in temp directories and plant fake secrets assembled at test time (the only literal is AWS's documented dummy AKIAIOSFODNN7EXAMPLE). They cover detection for every rule, a corpus of benign look-alikes, history detection of a secret added then deleted, moves, odd file names, --all, truncation, the baseline, and a stdio test that launches the installed server, drives all six tools over MCP, and asserts that no planted value or 16-character slice of one appears in any output or error.

License

MIT

Maintenance

ActivityMaintained
ResponsivenessNo recent community issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Enables scanning diffs or code blobs for leaked secrets, returning a verdict with severity and masked findings, all processed locally with no data sent externally.
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables scanning arbitrary text and added lines in unified git diffs for accidentally committed credentials, using precise vendor-format matches and entropy-based detection. All detected secrets are redacted before results are returned, helping coding agents and developers catch leaks without exposing full values.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to autonomously scan repositories and staged changes for leaked secrets, move exposed credentials into environment files, purge secrets from Git history, and verify remediation through deterministic tools.
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables AI agents to scan code or text content for hardcoded API keys, passwords, tokens, and private keys, reporting each finding by type, confidence, key name, and position. Secret values are never returned, so credentials can be located and addressed without leaving the machine.
    20 npm
    1
    MIT