Home / Blog / RBAC for AI Agents: Why Least Privilege Matters More Than You Think
RBAC AI agent RBAC AI security Claude Code access control least privilege

RBAC for AI Agents: Why Least Privilege Matters More Than You Think

By Sentrely Team · · 10 min read
Last updated

When a human joins your team, you don’t give them admin access to everything on day one. You give them the access they need to do their job, and expand it as they demonstrate judgment and need. This principle — least privilege — is fundamental to security for exactly one reason: if something goes wrong, the damage is bounded.

AI agents deserve the same treatment. They often don’t get it.

Why static RBAC isn’t enough for AI agents

Traditional RBAC was built for humans, who have stable roles — a developer is a developer all week. Agents don’t work that way: a single agent runs wildly different workflows hour to hour, touching different services and resources each time. Pin an agent to a fixed role and you get one of two bad outcomes. Either the role is broad enough to cover every possible workflow — and now it’s massively over-permissioned — or it’s tight enough to be safe and the agent’s tasks break the moment they stray. As the authorization vendor Oso frames it: humans have stable roles, agents execute dynamic workflows, so static RBAC tends to either break tasks or over-grant access.

The fix isn’t a bigger role. It’s a different model:

  • Deny-by-default. Nothing is allowed unless explicitly permitted.
  • Scope to task + resource + action, not to a persona — s3:GetObject on this prefix for this job, not “S3 access.”
  • Just-in-time elevation. Grant an extra permission for the moment it’s needed with a short TTL, then drop it — not a standing grant.
  • Continuous tightening. Watch what the agent actually uses and trim the rest.
  • Containment. A kill switch and per-agent identity so one misbehaving agent is bounded and instantly revocable.

That’s the model the rest of this guide implements — and it’s why agent access control belongs in a control plane, not in a static IAM role.

Why Agent RBAC Is Harder Than Human RBAC

With humans, access control is mostly about identity and role. Jordan is a developer, so Jordan gets developer access. Developers can push to feature branches but not main. Simple.

With agents, it’s more complicated for three reasons:

Agents are more prolific. A developer might make 20 git operations in a day. An agent might make 200 in an hour. The blast radius of a permissive policy scales with operation volume.

Agents don’t exercise judgment about scope. A developer who accidentally has access to a sensitive bucket will usually notice it’s not relevant to their work and leave it alone. An agent tasked with “find all CSV files” will find them everywhere it has access, without the social inhibitions that keep humans from overreaching.

Agent intent is harder to audit post-hoc. With humans, “Jordan deleted that table” is a starting point for a conversation. With an agent, “claude-ops-01 deleted that table” starts a reconstruction exercise. Better controls reduce the need for reconstruction.

The Structure of an Agent Policy

A well-designed agent policy specifies four things:

What services the agent can call. AWS, GitHub, Stripe, custom internal APIs, specific tools. Not “everything” — the specific services the agent’s job requires.

What actions within those services. s3:GetObject not s3:*. git:push not git:admin. charges:read not charges:write. This is where most policies are too permissive — it’s easier to write wildcards than to enumerate specific actions.

What resources those actions apply to. arn:aws:s3:::invoice-data/processed/* not arn:aws:s3:::*. The specific bucket prefix, the specific git repository, the specific Stripe resource type. Resources are where you contain blast radius.

What requires approval. The subset of allowed actions that are high enough risk to require human confirmation before execution. Pushing to protected branches. Deleting anything. External communications.

Here’s a realistic example:

project: invoice-processor
agents:
  claude-invoice-01:
    # Git: read any repo, push only to feature branches of invoice repos
    allow:
      - service: git
        actions: [clone, pull, fetch]
        resources: ["acme/*"]
      - service: git
        actions: [push]
        resources: ["acme/billing", "acme/invoices"]
        branches: ["feature/*", "fix/*"]

    # S3: read raw invoices, write processed output
    allow:
      - service: aws
        actions: ["s3:GetObject", "s3:ListBucket"]
        resources: ["arn:aws:s3:::invoice-data/raw/*"]
      - service: aws
        actions: ["s3:PutObject"]
        resources: ["arn:aws:s3:::invoice-data/processed/*"]

    # Stripe: read-only
    allow:
      - service: stripe
        actions: ["invoices:read", "customers:read"]

    # These require human approval
    require_approval:
      - service: git
        actions: [push]
        branches: ["main", "staging"]
      - service: aws
        actions: ["s3:DeleteObject"]

    # Hard limits
    deny:
      - service: aws
        actions: ["iam:*", "ec2:*", "rds:*"]
      - service: stripe
        actions: ["charges:create", "refunds:create", "customers:delete"]

This policy lets the agent do its job completely. It can’t do significant damage beyond its scope, even if it makes a mistake or is prompted maliciously.

Common Over-Permissioning Mistakes

s3:* on *. The most common AWS mistake. Every AWS action on every bucket. The agent only uses s3:GetObject, but you gave it s3:DeleteBucket just in case. This is how “clean up temp files” becomes “delete production data.”

Push access to all branches. Giving an agent push access to every branch, including main and release/*. The agent only touches feature branches in practice, but nothing stops it from pushing to main when it decides it’s done.

Shared credentials across agents. Ten agents, one set of credentials. Impossible to audit which agent took which action. Impossible to revoke one agent’s access without revoking all of them.

No resource constraints. Policies that specify action but not resource: “allow s3:GetObject” with no bucket specification. The agent can read any bucket it can discover.

Forget about tools, not just APIs. Policies that scope AWS and git but forget about custom tool integrations. If the agent can call arbitrary bash commands, or has a tool that can query any database table, the service-level policies are irrelevant.

Testing Your Policies

Write a policy, then try to break it. Prompt the agent to:

  • “Find all CSV files across all S3 buckets”
  • “Push the current state of main to the production server”
  • “Delete the temp files in the data directory”
  • “Check if there are any IAM users with admin access”

A well-scoped policy should result in 403 responses and “access denied” audit entries — not successful operations. If the agent can do these things, your policy is too broad.

Policy Version Control

Treat agent policies the same way you treat infrastructure code: version control, code review, change history.

A policy change is a security change. It should go through the same review process as any other security-relevant code. “Claude asked for more access so I gave it to him” is not an audit trail. A pull request with the requester, the rationale, and the reviewer is.

Sentrely enforces policies from YAML files committed to your project repository. Every policy change creates a git commit, which means every change has an author, a timestamp, and a diff.

The Minimum Viable Policy

If you’re starting from scratch and need a policy today, here’s the floor:

  1. No wildcard actions. List specific actions, even if the list is long.
  2. No wildcard resources. Scope to the specific buckets, repos, and resources the agent needs.
  3. Push to main requires approval. Always.
  4. Data deletion requires approval. Always.
  5. No IAM actions. Ever. Unless IAM management is the agent’s explicit job.

These five rules eliminate the most common blast radius scenarios while leaving most agent workflows intact. Start here and tighten from experience.

FAQ

What is RBAC for AI agents? Role-based access control adapted for autonomous agents: instead of mapping an agent to a broad human-style role, you grant deny-by-default permissions scoped to specific actions and resources for specific tasks, with per-agent identity and a kill switch. The goal is bounded blast radius — if the agent errs or is prompt-injected, the damage is contained.

Why doesn’t normal (static) RBAC work for AI agents? Static roles assume stable behavior. Agents run dynamic, varied workflows, so a fixed role either over-grants (broad enough for everything) or breaks tasks (too tight). Agents also act at high volume without judgment, so over-permissioning is far more dangerous than with a human.

How do I implement least privilege for a Claude Code agent? No wildcard actions or resources; scope to specific ARNs/repos/prefixes; default read-only and elevate just-in-time; require approval for pushes to main and any deletion; deny IAM by default. Enforce it at a control plane the agent can’t reconfigure, and version-control the policy.

How is this different from Claude Code’s built-in permissions? Native config is an allowlist-with-holes that the agent or developer can skip or talk around (see Claude Code security). Agent RBAC enforced at a gateway is deny-by-default, central, and tamper-proof — the agent holds no credentials and can’t widen its own scope.

// get-started

Put this into practice with Sentrely

Everything covered in this article is built into Sentrely's managed control plane. Get early access and have it running against your Claude agents in minutes.

AI agent stories, every 2 weeks

Real-world lessons on running AI agents in production — RBAC patterns, audit gotchas, approval workflows. No spam.

Unsubscribe anytime · No spam, ever

// talk-to-us

Tell us what you're building

We reply within one business day.

Platforms / tools you're using or evaluating *

Or email us directly at jordan@sentrely.com

get early access

Get early access

Leave your details and we'll reach out to get you set up.

No spam. We'll only use this to set up your access.