DEV Community

Authora Dev
Authora Dev

Posted on

Why agent RBAC is broken in most CLI frameworks (and how to fix it)

Last Tuesday, a “helpful” coding agent in a staging environment did exactly what it was told: clean up old resources.

It also had the same CLI credentials as the human who launched it.

So instead of deleting a temp bucket, it rotated secrets, modified deployment config, and opened a PR that looked totally legitimate. Nothing “hacked” us. The agent was authenticated. The problem was simpler:

we knew who started the agent, but not who the agent was.

That’s the gap a lot of CLI frameworks still have. They treat agents like scripts with a borrowed token. That works until you need to answer:

  • Which agent called this command?
  • What was it allowed to do?
  • Was it acting on behalf of a human?
  • Can I revoke just that agent without breaking everything else?
  • Do I have an audit trail that survives token sharing?

If you’re building agent workflows in a CLI, RBAC only works if agents have their own identity.

The usual anti-pattern

A lot of setups look like this:

export AWS_PROFILE=admin
claude-code run "fix the deployment issue"
Enter fullscreen mode Exit fullscreen mode

Now your agent is effectively an admin.

Even if you wrap this with “roles,” it’s usually still human RBAC, not agent RBAC. The agent inherits the operator’s power, and your logs show the human identity everywhere.

That creates 3 problems fast:

  1. No least privilege — agents get broad access by default
  2. No delegation model — “Alice allowed agent X to restart staging for 1 hour” isn’t encoded anywhere
  3. Bad auditability — you can’t separate human intent from agent execution

What “RBAC done right” looks like

The fix is not complicated conceptually:

  • Give every agent a real cryptographic identity
  • Issue short-lived credentials to that identity
  • Bind roles to the agent, not just the user
  • Record delegation chains when an agent acts for a human
  • Enforce policy at execution time, not just login time

Here’s the mental model:

[Human: alice]
      |
      | delegates "deploy:staging" for 30m
      v
[Agent: release-bot-7]
      |
      | presents signed identity + delegated scope
      v
[CLI / API / MCP server]
      |
      | checks:
      | - who is this agent?
      | - what role does it have?
      | - who delegated to it?
      | - is that delegation still valid?
      v
[Allowed action: restart staging only]
Enter fullscreen mode Exit fullscreen mode

That’s the difference between “an agent used Alice’s token” and “Alice delegated one narrow capability to a verified agent.”

A practical pattern for CLI frameworks

If you’re building this yourself, a decent baseline is:

1. Generate a keypair per agent

Ed25519 is a good default: fast, small, widely supported.

2. Register the public key

Store agent metadata like:

  • agent ID
  • owner/team
  • allowed roles
  • environment restrictions
  • expiration / rotation policy

3. Use delegated, short-lived tokens

If a human authorizes an agent action, mint a short-lived token with:

  • subject = agent
  • actor = human
  • scope = exact permission
  • TTL = minutes, not days

RFC 8693 token exchange is a good model here.

4. Enforce with policy

RBAC is the base layer. For anything non-trivial, add policy conditions:

  • only in staging
  • only during sprint hours
  • no secret reads
  • require approval for prod

If OPA fits your stack, use OPA. Don’t overbuild this.

A tiny runnable example

This example generates an Ed25519 identity for a CLI agent in Node.js.

npm install tweetnacl tweetnacl-util
node
Enter fullscreen mode Exit fullscreen mode
const nacl = require("tweetnacl");
const util = require("tweetnacl-util");

const kp = nacl.sign.keyPair();

const agentId = "release-bot-7";
const pub = util.encodeBase64(kp.publicKey);

console.log({
  agentId,
  algorithm: "Ed25519",
  publicKey: pub
});
Enter fullscreen mode Exit fullscreen mode

That’s not a full auth system, obviously. But it’s the important first step: the agent stops being an anonymous extension of a human session.

From there, your CLI can sign requests, your backend can verify them, and your policy engine can make decisions on the actual caller.

Where CLI frameworks usually go wrong

The failures I keep seeing are boring, which is why they’re dangerous:

  • Shared API keys for all agents
  • Static long-lived secrets checked into local config
  • Role names without enforcement (“agent_admin” means nothing if every command accepts it)
  • No per-agent revocation
  • No approval boundary for dangerous actions
  • No actor/subject distinction in logs

If your audit log says only alice@example.com deleted resource X, but an agent actually did it after a broad delegation 6 hours earlier, your incident review is already harder than it needs to be.

A better checklist

If you’re securing agents in a CLI framework, I’d start here:

  • [ ] Every agent has a unique cryptographic identity
  • [ ] Human and agent identities are distinct
  • [ ] Delegation is explicit, scoped, and short-lived
  • [ ] Roles are bound to agents, not inherited blindly
  • [ ] Sensitive actions can require approval
  • [ ] Audit logs capture both subject and actor
  • [ ] Keys can be rotated and agents revoked individually

You do not need a massive platform to start doing this correctly. Even a small internal CLI gets safer when you stop treating agents like glorified shell scripts.

Try it yourself

If you want to test your current setup:

The takeaway

CLI agents are getting real permissions now: deploys, code changes, secret access, incident response.

That means identity can’t be an afterthought.

RBAC for agents only works when agents are first-class principals. Give them identity, make delegation explicit, keep credentials short-lived, and enforce policy where execution happens.

How are you handling agent identity in your CLI workflows? Drop your approach below.

-- Authora team

This post was created with AI assistance.

Top comments (0)