Skip to content
Agentic Control Plane

Stop your AI agent from escalating IAM permissions — in three steps

David Crowe · 6 min read
governance defense-in-depth iam cloud-security

If your AI agent has access to your cloud account’s IAM API — and many do, because cloud-deploy tasks are exactly the work agents are useful for — it can grant itself permissions. One iam:AttachRolePolicy call binds an AdministratorAccess policy to whatever role it’s running under. From that moment, the agent can do anything in the account.

This isn’t theoretical. Some published “AI deployment helper” guides actively recommend giving the agent broad IAM permissions to “make it easier to debug.” That sets up exactly the failure mode where the agent is one prompt-injected README away from auto-promoting itself to admin.

The fix isn’t smarter prompting. The fix is keeping the privilege-escalation API path off the agent’s reachable surface entirely.

The IAM-escalation API surface

Across the major clouds, a small set of APIs let any caller upgrade their own (or another principal’s) permissions:

AWS:

  • iam:CreatePolicy, iam:CreatePolicyVersion, iam:SetDefaultPolicyVersion
  • iam:AttachRolePolicy, iam:AttachUserPolicy, iam:AttachGroupPolicy
  • iam:PutRolePolicy, iam:PutUserPolicy (inline)
  • iam:PassRole (delegation, indirect escalation)
  • sts:AssumeRole against over-permissioned target roles

GCP:

  • gcloud projects add-iam-policy-binding
  • gcloud iam service-accounts keys create (key creation = effective re-auth)
  • gcloud iam service-accounts add-iam-policy-binding (impersonation grant)

Azure:

  • az role assignment create
  • az role definition create

Any agent that can shell out to aws, gcloud, or az CLI has these in reach if the underlying credentials allow them. Most dev/ops kubeconfigs and CLI configs do — privilege restriction is usually applied at the role level, not at the API level, which means the agent can use whatever the role allows.

Why this is the worst-case blast radius

A destructive action you’ve already audited (a database deletion, a force-push) is bounded — you know what it costs and what it leaves you with. An IAM escalation is unbounded. Once the agent has admin, the next call can do anything: spin up resources, exfiltrate secrets, modify other roles, disable logging.

It’s also the failure mode that’s hardest to detect after the fact. If the agent grants itself permissions, then uses them, then revokes them — the audit trail of the use looks like authorized activity unless you specifically cross-reference the role’s effective permissions at the moment of each call.

For these reasons, IAM escalation is one of the OWASP Agentic Top 10’s named risks. It’s also one of the easiest to gate.

Three steps that put a gate between your agent and IAM

Step 1 — Install the hook

curl -sf https://agenticcontrolplane.com/install.sh | bash

Every CLI invocation routes through the hook. ACP classifies sub-commands, so aws iam ... lands under Bash.aws with the verb in the input.

Step 2 — Deny IAM-write APIs at every tier

This is one of the rare cases where you should deny in interactive tier too, not just background. There’s basically no legitimate reason an autonomous agent — whether you’re watching it or not — should be modifying IAM in real time. Permission changes belong in IaC behind a PR.

{
  "mode": "enforce",
  "tools": {
    "Bash.aws": {
      "background":  { "permission": "deny", "patterns": [
        { "match": "aws iam (create|attach|put|update|delete).*",  "permission": "deny" },
        { "match": "aws sts assume-role.*",                          "permission": "deny" }
      ]},
      "interactive": { "permission": "allow", "patterns": [
        { "match": "aws iam (create|attach|put|update|delete).*",  "permission": "deny" },
        { "match": "aws iam list.*",                                  "permission": "allow" },
        { "match": "aws iam get.*",                                   "permission": "allow" }
      ]}
    },
    "Bash.gcloud": {
      "patterns": [
        { "match": "gcloud .*add-iam-policy-binding.*",               "permission": "deny" },
        { "match": "gcloud iam service-accounts keys create.*",       "permission": "deny" },
        { "match": "gcloud iam roles create.*",                       "permission": "deny" }
      ]
    },
    "Bash.az": {
      "patterns": [
        { "match": "az role (assignment|definition) create.*",        "permission": "deny" }
      ]
    }
  }
}

The semantic: read-only IAM operations (list, get, describe) are allowed — agents debugging an issue often need to see current bindings. Mutating IAM is denied at every tier. If you genuinely need the agent to modify IAM in some edge case, the path is through a separate explicit allowlist for that one task, not via the always-on policy.

Step 3 — Bind end-user identity, per request

Even if a credential with IAM-write permissions is technically reachable on the machine, ACP’s per-user policy lookup means the user’s IdP scope determines what’s allowed:

from acp_governance import set_context

set_context(
    user_token=request.headers["Authorization"],
    agent_name="cloud-deploy-helper",
    agent_tier="background",
)

If the user’s IdP doesn’t include the iam:write scope, the agent can’t do IAM writes — even if the underlying AWS credential has the permission. This is belt-and-suspenders defense: deny via tool-level pattern, deny via identity-scoped policy.

(Free fourth step) — Audit log

Every IAM call attempt — allowed or denied — writes a structured audit row. The dashboard surfaces the pattern of denied IAM-write calls so an attempted escalation is visible the moment it happens, not at the next quarterly access review.

Set up a dashboard alert: “any denied call against Bash.aws matching aws iam (create|attach|put) notifies you within seconds. Most attempted-escalation incidents go undetected for weeks. This catches them in real time.

The total time investment

  • One curl command (Step 1): ~30 seconds
  • IAM-API deny patterns across AWS / GCP / Azure (Step 2): ~5 minutes
  • One handler binding (Step 3): ~1 minute

Five to seven minutes from blank slate to “an autonomous agent in this environment cannot grant itself or any other principal additional permissions, cannot create access keys for service accounts, and cannot impersonate higher-privileged roles — regardless of what the underlying cloud credentials technically allow.”

The right amount of IAM-write authority for an autonomous agent is zero. Everything an agent legitimately needs to do in the cloud is achievable with read-only IAM and per-task scoped credentials issued separately. The agent that can escalate is the agent that eventually does — and that’s the bill that wakes you up.

AgenticControlPlane.com

Get the next post
Agentic governance, AgentGovBench updates, the occasional incident post-mortem. One email per post. No marketing fluff.
Share: Twitter LinkedIn
Related posts

← back to blog