Pages

Sunday, 26 July 2026

Credential bleed: what happens when your MCP server trusts the wrong thing

 

I set up an MCP server for MySQL last month. Took maybe twenty minutes. FastMCP, running on port 9100, exposing a handful of database tools to any agent that connected to it.

Then I asked myself a question I should've asked before writing a single line of code. What exactly is this server trusting, and who gave it permission to trust that?

Turns out, the answer was: whatever connected to it.

Here's the thing about MCP servers that nobody warns you about when you're following a quickstart guide. The server doesn't inherently know the difference between "an agent I authorized to run read queries" and "an agent that happened to find my endpoint." If your auth model is weak or missing, every tool you expose is available to every connection that shows up. Credentials don't need to be stolen. They just need to be reachable.

I built this specific setup as a demo, deliberately, to see how bad it could actually get. Not theoretical. A real MySQL MCP server, real credential handling, real tools exposed. And what I found is that credential bleed isn't some exotic attack. its the default state of a lot of MCP setups people are shipping right now, without realizing it.

Think about what an MCP server actually does. It sits between an agent and a real system, translating natural language intent into real actions. Real database queries. Real Terraform applies. Real file writes. Somewhere in that translation layer, credentials have to live. And if that layer trusts the connection instead of the identity, you don't have an access control system. You have an open door with a "please don't" sign on it.

This is the same failure mode I saw with a Terraform agent demo I built separately. An ambiguous prompt walked straight through terraform_plan into terraform_apply and created a real S3 bucket in AWS. Nobody meant for that to happen. The agent didn't misbehave. The boundary that was supposed to stop it simply wasn't there. Same root cause, different door.

The uncomfortable part is that this scales with adoption, not against it. The more useful MCP servers get, the more tools get exposed, the more valuable the thing sitting behind that unguarded connection becomes. A vulnerable server nobody uses is a curiosity. A vulnerable server your whole team routes agent traffic through is a real incident waiting on a slow Tuesday.

None of this means don't build MCP servers. It means stop treating the connection as the identity. An agent proving it can reach your server is not the same as an agent proving it should be trusted with what's behind it. Ephemeral credentials, scoped tools, intent validation before execution, these aren't nice-to-haves you add later. They're the actual product. Everything else is just a demo that works until it doesn't.

I'll probably write up the full technical breakdown of the MySQL demo separately. For now, if you're standing up an MCP server this week, ask the boring question first. Not "does it work." Trust what, exactly.

I built a pipeline to auto-post my Telegram channel everywhere. Then I stopped.

 

Auto-posting my Telegram channel posts everywhere sounded like a dream. Then I actually built it.

The plan was simple. Write one post on my Telegram channel (@securedevops). Let a pipeline pick it up. Reformat it for each platform. Push it out to LinkedIn, Twitter, Instagram, Facebook, Dev.to. Zero manual work after hitting publish once.

I built it in n8n. A webhook catches new posts from the channel. A dedup check makes sure nothing gets posted twice. Then a handoff point where ChatGPT would rewrite the post per platform, and push it live everywhere.

Sounds clean right? It mostly worked. Until it didn't.

Here's where it broke. I was using ngrok's free tier to expose the webhook. Every time my machine restarted, the URL changed. Which meant every time I restarted, I had to manually go re-register the new URL with Telegram. A pipeline that's supposed to save me time now needed me to babysit it every morning. Not exactly "fully automated."

And the more embarrassing part. the actual multi-platform posting, the part that was supposed to save the most time, never got finished. I built the capture layer. I built the dedup layer. I stopped right before the part that mattered most.

Thinking about it now, this wasn't really an automation failure. It was a sequencing mistake. I built the fun part first. Webhooks, dedup logic, the architecture diagram in my head looking clean. The boring part, a stable public URL, I left for later. Later never came.

This keeps happening in infra work and I don't think its a coincidence. The AI reformatting step, the multi-platform posting, that was the exciting 20%. Getting a reliable endpoint that survives a restart was the unglamorous 80%. Everyone wants to build the 20%. Almost nobody wants to build the 80%. But the 80% is usually what decides if the thing actually runs unattended or not.

So the pipeline still sits there. Half built. Working, technically, if I remember to re-register the URL by hand.

Anyone else have an automation project that stalled right at the boring part? curious if this is a me problem or a universal one.

#DevOps #Automation #n8n #BuildInPublic #AIAgents