~/ / AI articles / 2,117 valid secrets in public MCP config files: what GitGuardian found, and how to check yours
2,117 valid secrets in public MCP config files: what GitGuardian found, and how to check yours
A configuration file that tells an AI application which MCP servers to run often needs a key. GitGuardian's State of Secrets Sprawl 2026 report counted 24,008 unique secrets in MCP-related configuration files on public GitHub, and 2,117 of them were valid credentials. This article summarizes the report, explains what Claude Code's documentation says about project configuration files, and lets you check your own.
Published: · Checked against the official sources on 2026-10-24. This article summarizes them and does not replace them.
What the report found
- GitGuardian published its State of Secrets Sprawl 2026 report on 17 March 2026. Its data covers 2025.
- It counted 24,008 unique secrets exposed in MCP-related configuration files across public GitHub, including 2,117 unique valid credentials.
- In 2025 alone, 28.65 million new hardcoded secrets were added to public GitHub commits, which the report calls a 34% increase year over year.
- AI service secrets reached 1,275,105, up 81% year over year.
- The report says the problem is often driven by the documentation itself, which encourages unsafe patterns: putting API keys directly into configuration files, command-line arguments or embedded connection strings.
Why a project's MCP file is easy to leak
Claude Code stores project-scoped MCP servers in a .mcp.json file at the project's root directory, and its documentation describes that file as shared through version control. A key typed into it is visible to everyone who can read the repository.
| Scope | Where it is stored | Who sees it |
|---|---|---|
| Local | ~/.claude.json, under the project's path | The current project, private to you |
| Project | .mcp.json in the project root | The current project, shared through version control |
| User | ~/.claude.json | All your projects |
Keep the key out of the file
- Claude Code expands ${VAR} and ${VAR:-default} in command, args, env, url and headers, so the file can name a variable instead of holding the value. The documentation's own example writes a header as Authorization: Bearer ${API_KEY}.
- If a variable is not set and has no default, the configuration still loads. Claude Code shows a warning and uses the text ${VAR} as written.
- In the url and headers of a remote server, some credential variables read as empty even when they are set. The documentation names ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN, AWS_BEARER_TOKEN_BEDROCK, HTTPS_PROXY and NPM_TOKEN as examples, and says that a variable named API_KEY expands as written.
- A value written in args or url is also stored in the file, so the report's warning about command-line arguments and embedded connection strings applies there as well.
Check your file
The checker below reads a .mcp.json or claude_desktop_config.json in your browser. It flags values that look like secrets written into args, env and headers, using the same detectors as the Prompt Redactor, and variable references that Claude Code reads as empty. The detection is a heuristic, so it can miss a secret or flag a harmless value.
Try it: MCP Config Checker
Rules checked against the documentation on 2026-10-23.
Documentation: Claude Code / Model Context Protocol / VS Code
Not checked: whether a command exists, whether a package installs, whether a remote server answers, and settings that other applications read differently.
Everything runs in your browser. The configuration is not uploaded.
Before you paste a config into an AI chat
People often paste a configuration file into an AI chat to ask why a server does not start. The Prompt Redactor masks API keys, tokens, passwords and personal data in the text, and can restore them in the answer, all in your browser.
Try it: Prompt Redactor
Masked text
The masked text appears here.
This finds text with a recognizable shape. It cannot find confidential information written in ordinary sentences, so not finding something does not mean it is safe.
Read the masked text before you send it.
Key formats were checked against vendor documentation and RFCs on 2026-10-23.
Everything runs in your browser. Neither your text nor the restore table is uploaded.
If a secret was already committed
- GitHub's documentation says the first step is to revoke or rotate the secret, so that it can no longer be used for access.
- After rotating, rewriting the repository history may not be warranted, because revoking the secret may be enough to solve the problem.
- If the commit exists in forks, it stays accessible there. GitHub cannot give you the contact details of the fork owners.
- Commits can stay reachable by their SHA-1 hashes in cached views on GitHub. GitHub Support can remove cached views and references for sensitive data whose risk cannot be reduced by rotating credentials.