The Model Context Protocol is how AI agents reach your tools and data. A single JSON file decides which servers an agent may talk to and what credentials it carries. That file is now sitting in a lot of public repositories.
Working through this in production? See how we run a AI security assessment.
So we scanned 463 of them.
This is the first published red-team finding from Data Science & Engineering Experts. Everything below is aggregate. No repository is named, and every credential we found was privately disclosed to its owner before this was written.
What we found
463 publicly published MCP configuration files, declaring 998 servers between them. 31% carried at least one authentication-posture finding.
| Finding | Count | Severity |
|---|---|---|
| Remote server declaring no authentication | 109 | Medium |
| Placeholder where a credential belongs | 113 | Low |
| Real credential committed into config | 27 | High |
| High-entropy value in an auth field | 16 | High |
Remote endpoint over cleartext http:// |
5 | High |
| Configs carrying a vendor-format credential (GitHub, Slack, JWT) | 3 | Critical |
Every row is a count of findings except the last, which counts configurations, and it excludes a fourth that turned out to be a documented example value, for reasons covered below.
The headline is not the leaked keys
It is this: of 163 remote MCP servers in the corpus, 109 declare no authentication at all. Two thirds.
Leaked credentials are a familiar problem with a familiar fix. An ecosystem where the default shape of a remote connection has no auth on it is a different kind of problem, and it is a design-surface problem rather than a carelessness problem. People are not forgetting to add authentication. The configuration format makes omitting it the path of least resistance, and there is no gate anywhere in a normal workflow that objects.
Three real credentials, privately disclosed
Three configurations carried values matching live credential formats: a GitHub personal access token, a Slack token, and a JWT.
We did not test any of them. Validating someone else’s key against a live service is unauthorized access, not research, so all three findings are format pattern-matches and nothing more. Each owner was contacted privately before publication, with the specific note that deleting the file does not help because the value remains in git history.
A fourth apparent AWS key turned out to be the AKIA…EXAMPLE placeholder that
appears throughout Amazon’s own public documentation, sitting in the test
fixtures of a security tool. Working exactly as intended, and excluded from
every count above.
The part most write-ups leave out
Our first scan reported 145 committed credentials, not 27.
Before publishing that number we looked at the shapes of the values behind it.
107 of them were placeholders: YOUR KEY GOES HERE, xxx, <your-api-key>.
Template slots in example configs, not secrets. The rest were reference forms our
detector did not recognise:
${GITHUB_TOKEN:-}, shell expansion with a defaultop://vault/item/field, a 1Password reference~/.config/app/keys.json, a path to a credential file, not the credential
All four are what a careful operator does. We were flagging them as leaks.
We fixed the detector, split placeholders into their own low-severity rule, and re-ran. 145 became 27.
That correction matters more to us than the finding. A five-times overstatement would have been the most shareable number in this post, and it would have been wrong. The same tool had shipped a day earlier with 100% test coverage and 843 passing tests. The very first run against a real configuration file produced three false positives, because every test fixture used the shape the author imagined rather than the shape the world uses.
Coverage measures whether your code ran. It does not measure whether you were right.
What to do about it
If you publish MCP configs, the fix is one line. Configs accept environment
references, so "Authorization": "Bearer ${TOKEN}" keeps the secret out of the
repository. If a credential has already been committed, rotate it at the
provider. Removing the file leaves it in history.
If you operate remote MCP servers, assume no client is authenticating unless you require it. Two thirds of the ones we saw are not.
If you run agents in production, put a gate in CI. We open-sourced ours: mcp-warden audits MCP auth posture statically (no server spawned, no network touched) and exits non-zero so a pipeline has to answer for it.
pip install mcp-warden-cli
mcp-warden auth audit .mcp.json
Method and ethics
Corpus assembled via GitHub code search across public repositories, restricted to files already published by their owners. Scanning was fully static: no server was started, no endpoint contacted, no credential validated.
All 463 configurations were destroyed on every DSE host before this was written. We retained only aggregate counts and a repository-and-rule worklist for disclosure. We are a security firm; holding other people’s credentials while writing about credential hygiene is not a position we are willing to occupy.
Data Science & Engineering Experts builds data and AI security for US government and enterprise. If you are deploying agents and want to know what your configuration surface actually looks like, get in touch.