Web Development

I Let My AI Agent Read My AWS Credentials. Here's What I Learned

A

Admin User

Author

Jun 21, 2026
5 min read
19 views
I Let My AI Agent Read My AWS Credentials. Here's What I Learned

I shipped an HTML injection vulnerability in an AI chatbot three years ago. The model spit out some HTML, I rendered it straight to the page, and a user discovered they could inject arbitrary content. It was humbling, and I thought I'd learned the lesson: never trust what an LLM gives you.

Last month, I started experimenting with MCP servers to give my coding agents actual capabilities—read files, hit APIs, query databases. The appeal is obvious: your agent stops being a text generator and becomes something that can do things. But about halfway through wiring up my first tool, I realized I'd almost made a much worse mistake than that old chatbot bug. I was about to give my agent read access to ~/.aws/credentials and assume the sandbox would protect me. It wouldn't have.

The real problem with AI agents isn't just what they do. It's what they believe.

The Hidden Half of the Threat

When we talk about securing AI agents, the conversation almost always centers on destructive actions. What if the agent deletes files? Force-pushes production? Runs an rm command it shouldn't? These are the fears that make headlines, and they're legitimate. But they're only half the problem.

The other half is quieter and harder to reason about. An MCP server returns data—an API response, a database row, an email thread. Somewhere in that payload, there might be text that reads like an instruction. The model can't reliably distinguish between an instruction you gave it and an instruction buried in returned data. They come through the same channel.

This is where MCP becomes genuinely risky in ways that regular tool integration isn't. You're not just handing your agent a capability—you're giving it a channel to receive untrusted input from external systems. And that input can influence what the agent tries to do next.

Treating Tool Output Like Form Input

Here's the mental model that saved me: whatever an MCP server returns is exactly like a string a stranger typed into a form on your website. It's not "data from my trusted server." It's data from outside that happens to arrive through a tool I connected.

When you reframe it that way, your defensive posture changes. You don't pass raw output into the next command. You don't skip validation because it came from a service you trust. And you absolutely don't let imperative sentences buried in returned documents quietly become agent directives.

The challenge is that the tooling can't do this for you. There's no flag that knows whether a returned string is a legitimate API result or a planted instruction. That judgment lives in how you wire the data. This is defensive programming, and it's on you.

Walls, Not Manners

The destructive-action threat does have a technical answer, but it's easy to half-implement. Most people rely on asking the model nicely not to do dangerous things. That doesn't work. You need walls.

In Claude Code, that wall is the sandbox. When enabled, bash execution gets isolated at the OS level. But here's what surprised me: the sandbox restricts writes and execution, but by default it still allows reads across most of your machine.

{
  "sandbox": {
    "enabled": true,
    "allowUnsandboxedCommands": false
  },
  "permissions": {
    "deny": [
      "Bash(rm -rf *)",
      "Bash(curl *)",
      "Bash(wget *)",
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(~/.ssh/**)",
      "Read(~/.aws/**)"
    ]
  }
}

That deny list is where the real protection happens. The sandbox stops the agent from executing something destructive. The permission rules stop it from reading secrets and exfiltrating them. You need both. Neither covers for the other.

What I'm Actually Doing Now

Before connecting any MCP server, I ask three questions:

First, do I trust the source? An MCP server isn't a browser tab. It's code running in your agent loop with a direct channel into your decision-making. That's part of your trust boundary.

Second, what's the worst command it could talk my agent into, and is that blocked by deny rules? This is where you think concretely about the attack chain, not abstractly about "security."

Third, will the output be treated as untrusted everywhere it lands? Or will it slip through as data that "came from a tool so it must be safe"?

The other habit I've adopted: if a CLI already does the job, don't build an MCP server. I call wp-cli from a skill when I need it rather than wrapping it in an always-connected server. One less attack surface. One less data channel to distrust.

The Question Worth Asking

I'm curious how many production setups are running MCP servers with sandboxing enabled but without those deny rules. Or with deny rules that don't actually cover the paths where secrets live. The configuration looks secure, but the gaps are subtle.

What's your threat model when you connect a new MCP server? I'd genuinely like to know what you check for.

Source: This post was inspired by "Connecting an MCP server gives your agent hands. It also gives a stranger a way in." by Dev.to. Read the original article

Share this article

Written by Adil Sher

Full stack developer building high-traffic platforms, AI services, and custom web applications. Explore my portfolio, learn about my background, or get in touch.

Related Articles

We Built an AI Code Tool. Then Reality Hit.
Web Development Jul 16

We Built an AI Code Tool. Then Reality Hit.

Six months ago, my team shipped an AI-powered code suggestion feature. The demos were clean. The founder was excited. We had benchmarks showing 85% accuracy on test cases. Then a client tried it on their actual codebase—a three-year-old Next.js monorepo with custom tooling, weird...