You're debugging a config issue in src/config.ts. You ask your AI agent to take a look. The file has a console.log statement you added last Tuesday while debugging โ one that dumps the entire config object, including DATABASE_URL with an embedded password and AWS_SECRET_ACCESS_KEY pulled directly from process.env. The agent reads the file, executes its tools, and now your production credentials are sitting in its context window. It might summarize them. Include them in generated code. Pass them to another tool that logs everything by default. None of this requires the AI agent to be malicious. It just needs to be helpful. That's what makes this class of vulnerability so insidious โ there's no breach, no attacker, no social engineering. Just an AI doing exactly what you asked it to do: read the file and help you fix the bug.
The Three Ways Secrets Leak
The first vector is hardcoded credentials in source files. A connection string with a password embedded directly in the URL, a token copied "just for testing," or a DATABASE_URL that looks like postgres://admin:p@ssw0rd123@prod.db.internal:5432/app. Any agent reading any file that imports this config now has your production database credentials. The second is .env files missing from .gitignore. Your environment file contains 40 keys โ AWS credentials, Stripe keys, JWT secrets, OAuth tokens, encryption keys. One git push and it's in the repository forever. Even if you delete it later, Git history preserves it. The agent doesn't know this is dangerous. It reads files. That's its job. The third is console.log statements that never got removed. The debug line committed on Friday that nobody notices until Monday morning โ except by then, every time your app starts, it dumps credentials to stdout. If you have log aggregation running, those secrets are now sitting in your observability platform alongside terabytes of other data you can't easily purge.
How the Scanner Works
The env-secret-exposure-analyzer-mcp MCP server addresses all three vectors with three distinct tools. scan_for_secrets scans source files, config files, and .env files for over 20 patterns covering AWS keys, GitHub tokens, Stripe webhook secrets (whsec_), Google OAuth credentials (GOCSPX-), database URLs with embedded passwords, JWT secrets, encryption keys, and more. The scanner never returns the full secret value in its output โ only a masked preview to prevent the tool itself from becoming an exposure vector. check_gitignore_coverage walks your project root and verifies that sensitive files like .env, .env.local, secrets.json, private keys, and certificates are covered by .gitignore. It correctly ignores .env.example and .env.sample since those are supposed to be committed with placeholder values. scan_for_log_leaks hunts for console.log or logger calls that print process.env variables or objects containing secret-sounding names โ catching both direct leaks like console.log(process.env.AWS_SECRET_ACCESS_KEY) and indirect ones like console.log("Config:", JSON.stringify(config)) where config was built from environment variables.
The Irony of Building a Secret Scanner
When writing tests for the tool, the author created fixture files with fake-but-realistic secrets: GITHUB_TOKEN=ghp_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA and AWS_ACCESS_KEY_ID=AKIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA. GitHub push protection blocked the commit โ because its own test fixtures looked too much like real secrets. Even obviously fake ones following the pattern ghp_ followed by 40 characters matched the GitHub token format exactly. The fix involved creating fixture files programmatically in os.tmpdir() at test time so they never touched the git repository. The tests pass, pushes go through cleanly, and somewhere a security engineer nods approvingly at the irony of a secret scanner being caught by another secret scanner's test suite.
Does It Actually Work?
After publishing, the author verified the full MCP protocol layer โ not just isolated functions but the actual stdio transport that Claude Desktop uses. Testing involved piping JSON-RPC messages directly to the Node.js server process and confirming proper responses with severity levels (CRITICAL/HIGH), file paths, line numbers, and masked previews. Error handling was also tested: bad paths return isError: true with readable messages rather than crashing the server.
Key Takeaways
- AI agents don't need to be malicious to expose your secrets โ they just need to read files containing them while being helpful
- The three primary exposure vectors are hardcoded credentials, .env files not in .gitignore, and console.log statements that dump config objects
- MCP servers can provide agents with context they structurally cannot have on their own โ like knowing which patterns represent real secrets versus legitimate code
- When building secret-scanning tools, generate test fixtures programmatically to avoid triggering other security systems
The Bottom Line
This is the shape of AI agent security in 2026: not fighting attackers, but preventing your own helpful assistant from accidentally propagating credentials across every tool call it makes. The agents aren't the threat โ they're just too eager to use whatever information crosses their context window. Tools like this one give them the judgment they lack.