Yesterday I argued that your agent config is the attack surface — that the dangerous part of an agent setup is not the model but the files that tell it what to trust. The empirical version of that argument was already sitting in a report published in March. According to GitGuardian’s 2026 State of Secrets Sprawl report, dated March 17, there were 24,008 unique secrets exposed in MCP configuration files on public GitHub, and 2,117 of them were still valid at scan time. The number was there for two months. It took this week’s run of agent-targeting CVEs for me to go back and actually read it.
This is not a careless-developer story
The easy reading is that some developers were sloppy and committed their keys. That reading lets the tooling off the hook, and the tooling is where the story actually lives. Twenty-four thousand exposed secrets in one file type is not a distribution of individual mistakes. It is a property of a format. MCP configuration puts API keys in plaintext, right next to the transport declaration, in a file that lives in the repository alongside everything else. When a number gets that large, you are not looking at bad luck repeated thousands of times. You are looking at a design that makes the mistake the default and the safe path the exception.
The format made it inevitable
MCP config wears the same clothes as .eslintrc or .prettierrc. It is a dotfile, it sits at the project root or in a .cursor or .claude directory, and it carries the strong cultural signal that dotfiles are safe to commit — because for thirty years, they were. Linter configs and formatter rules belong in version control. Nothing about the visual grammar of an MCP config file warns you that this particular dotfile holds a live provider credential and the last one held a tab-width preference. The file looks identical to the things you are supposed to commit, so it gets committed, and the credential rides along.
How the key actually gets out
The leak is rarely dramatic. Three quiet paths cover most of it. The first is the initial commit: a developer wires up an MCP server, pastes the key in to make it work, gets the agent running, and commits the whole working directory in one git add . before the key ever moves to an environment variable. The second is the fork or the flip to public: a private repo with an inline key gets opened up months later, and the key rides into visibility without anyone touching the file. The third is the log: a CI step prints its environment for debugging, the MCP config is in that environment, and the key lands in a build log that stays readable to anyone who finds the URL. None of these require carelessness in the moment. They require only that the key was ever in the file — which is exactly what the format encourages from the first quickstart onward.
The pattern is in the quickstart
The part of GitGuardian’s finding that should bother tool authors most is their observation that popular MCP setup guides recommend putting API keys directly into configuration files. That is the root cause stated plainly. The insecure pattern is not buried in an advanced section that experienced developers find and misuse. It is in the quickstart — the first code block a beginner copies, the one that has to work in under five minutes or the tool loses the user. Quickstarts optimize for the demo succeeding, and an inline key always makes the demo succeed. Every quickstart that hardcodes a key is manufacturing future entries in next year’s version of this report, and the people who will pay for it are the ones who trusted the official getting-started page.
The steelman
The honest counter-argument is that this is fixable and is being fixed. The SDKs do support environment-variable substitution — you can write ${env:OPENAI_API_KEY} and keep the secret out of the file entirely. Some tools now ship that form as their default example. The standard is young, the docs are improving, and a chunk of those 24,008 secrets came from an early period when the substitution syntax was less prominent than it is now. All of that is true, and I accept it. It does not change what to do today, because the report is a snapshot of what is currently sitting in public repositories, and “the docs are getting better” does not rotate a key that is already exposed.
What this means in practice
My stance is the one the number forces. Treat any mcp.json, any agent.json, any skills/*.yml exactly the way you treat a .env file: gitignored by default, never committed, audited on a schedule rather than after an incident. The dotfile aesthetic is the trap, so override it deliberately — the file looks safe, so you have to decide, once and categorically, that this class of file is not. The thing that changed this week was not the data. The data was published in March. What changed is that the agent CVEs caught up to the configuration, and the gap between “this is theoretically the attack surface” and “here are 2,117 live keys that prove it” finally closed. The next question is what all this agent activity is actually producing, and whether the headline number everyone quotes — the share of code that is now AI-written — means what people think it means. That is the 51% number, and what “assisted” hides. For the operational version of locking this down, see hardening your agent supply chain; for where the footprint came from, parallel agents and the per-developer meter.