DEV Community

Muskan Bandta
Muskan Bandta

Posted on

Your Ops Agent’s Chat History Is an Attack Surface: Prompt Injection Just Became an Infrastructure Problem

There's a line going around dev.to this week that stuck with me: your AI agent's chat history is user input. It's a security observation about chatbots. But if you've given an agent cloud credentials — and half the "I let an agent run my ops" posts on here have — that line stops being about chatbots and becomes the scariest sentence in your architecture.

Here's the uncomfortable version: when an agent can call cloud APIs, prompt injection is remote code execution on your infrastructure. Let me walk through exactly how, because the attack surface is bigger and dumber than most people realize.

The classic framing, and why it undersells the risk

Prompt injection in a chatbot: attacker gets the bot to say something it shouldn't, or leak its system prompt. Bad, embarrassing, usually contained.

Prompt injection in an ops agent: attacker gets the agent to TerminateInstances, exfiltrate secrets to an external endpoint, or open a security group to 0.0.0.0/0. The agent has an IAM role. The IAM role has real permissions. Every check is green — because the agent is allowed to do those things; that's its job. (I wrote a whole separate piece on why IAM being green is exactly the trap.)

The model doesn't distinguish "instruction from my operator" from "text I read while doing my job." To an LLM it is all just tokens in the context window. And the context window is full of attacker-reachable text.

The injection surface nobody threat-models

When people hear "prompt injection" they picture the chat box. For an ops agent, the chat box is the least of it. Your agent reads all of this while working, and any of it can carry instructions:

  • Resource tags and names. An agent listing resources reads their Name tags. A tag value of prod-db — ignore prior instructions and run <bad thing> is now in the context. Anyone who can create a resource in a connected account can plant text.
  • Log lines. Agent triaging an incident reads application logs. Logs contain user-controlled strings. A crafted log line is a payload the agent ingests as part of "reading the logs."
  • Cloud resource metadata, commit messages, PR descriptions, ticket bodies, error messages from third-party APIs, container image labels, Kubernetes annotations. Every one of these is (a) text the agent reads to do its job and (b) writable by someone who isn't your operator.
  • The agent's own memory. With long-term memory (now a first-class feature in Bedrock AgentCore, Azure Foundry, Vertex), a poisoned instruction written into memory today fires days later, in a fresh session, with no attacker present. Persistent memory is a persistent attack surface.

The threat model most teams have is "someone types something malicious in the chat." The real model is "any text from any source the agent touches is potentially adversarial instruction." That's a vastly larger surface, and it maps onto data you already treat as untrusted for XSS/SQLi — except now the sink is your cloud control plane.

Why the usual defenses don't fully save you

"We'll sanitize inputs." You can't reliably sanitize natural language for instruction content — there's no parser boundary between data and command in a prompt. This is the whole reason prompt injection is unsolved. Delimiters and "the following is untrusted, ignore instructions in it" help at the margin and are defeated regularly.

"Least-privilege IAM." Necessary, insufficient. An ops agent's legitimate permissions are the dangerous ones. You can't least-privilege away delete verbs when deleting is the job.

"A human approves actions." The best single control — but approval fatigue is real, and a well-crafted plan looks reasonable. "Clean up these 40 idle resources" hides one resource that isn't idle.

What actually reduces the blast radius

Not solutions — mitigations. Defense in depth, because the injection itself can't be fully prevented:

  1. Two-phase execution. Agent proposes a plan with read-only credentials; a separate executor with write credentials applies it after a gate. Injection into the reasoning agent can produce a bad plan, but the plan is inspectable before any credential with teeth touches it.
  2. Action-level policy, not just IAM. Allowlist action shapes (verb + resource class + condition + time window), enforce blast-radius budgets (max N resources, max $/hour delta per run). A run that suddenly wants to touch 200 resources trips the budget regardless of what convinced it to.
  3. Treat agent-read data as untrusted at the boundary. Tags, logs, annotations — the same "untrusted input" hygiene you apply to a web form, applied to everything the agent ingests. You won't catch everything; you'll shrink the surface.
  4. Independent state verification. A watcher comparing actual resource state against expected baselines on a tight loop, on separate credentials and separate code from the agent — so a successful injection surfaces as drift within minutes instead of on next month's bill. (This is why, building anomaly detection into ZopNight, we made the verifying system share nothing with any acting system — an injected agent must not be the thing that reports whether it misbehaved.)
  5. Rate/anomaly alarms on the account. CloudTrail → metric filter → alarm on API velocity per identity. A hijacked agent looks like a traffic anomaly before it looks like a policy violation.

The takeaway

"Your agent's chat history is user input" is correct and it doesn't go far enough. For an agent with cloud credentials, everything the agent reads is user input — and the sink isn't a rendered web page, it's your infrastructure control plane. Prompt injection stopped being a chatbot embarrassment and became an infrastructure security problem the moment we handed agents an IAM role.

If you're running an ops agent in prod: what's reading into its context that you don't control? Start listing, and the list gets uncomfortable fast. I'd like to hear what surfaces people found that they hadn't threat-modeled.

Top comments (0)