DEV Community

Anusha Mukka
Anusha Mukka

Posted on

Revocation Is the Real Test: If You Cannot Kill One Agent in Minutes, You Never Controlled It

Forty teams told VentureBeat they enforce scoped agent identities. Seventeen of them then admitted their agents still share the credentials underneath. The control that separates a program from a claim is not scoping. It is revocation, timed.

Pick one agent you can safely take offline. Now time yourself.

How long does it take to revoke that agent's access, and only that agent's access, so its next request fails? If the answer starts with finding out which key it uses, you have your result already. You do not have an identity program with a revocation gap. You have an inventory problem wearing an identity program's clothes.

VentureBeat ran the numbers in September 2026. Its Agentic Security and Identity survey asked 102 enterprises how they secure and revoke AI agent access. Forty described a program that enforces scoped identities and runtime permission checks. Seventeen of those 40 then said some or most of their agents still share credentials. Across the full sample, 35 give each agent its own identity, 45 share to some degree, and 22 could not say how their agents authenticate at all.

The revocation answers are worse than the sharing answers. Only 14 of the 102 said a named owner could revoke access within minutes. Forty-five pointed to a security or platform team that could do it within hours. Seventeen estimated more than a day, or said they would need to trace the credential first. Ten were not certain they could revoke every agent. Fourteen did not know.

So the modal enterprise, faced with a compromised agent at 2 a.m., is looking at hours of work, a trace it has not done yet, or a shared key it cannot pull without breaking other workloads. That is the gap this piece fills. Every explainer covers issuing scoped credentials. Almost none cover killing one, under pressure, without collateral damage. Issuance is the easy half. Revocation is the test.

Understand Why Shared Credentials Break Revocation First

A credential answers two questions at once: who is asking, and should they be allowed. A shared credential answers the second question and garbles the first. When five agents present the same API key, the key authenticates a request without identifying which agent sent it. Your logs show the key. They do not show the agent.

That garbling is survivable on a quiet day. It is fatal during an incident, because revocation is a per-agent operation and a shared key is not a per-agent object. Pull the key and you have revoked five agents, four of them innocent, some of them mid-task for real users. Leave the key and the compromised agent keeps working until rotation, which the survey suggests may be tomorrow.

Andrew Obadiaru, CISO at Cobalt, told VentureBeat that agents break the service-account model at exactly this point. For a conventional service account, revoking the credential stops further requests. With agents, he said, even when you revoke those tokens, they move so fast that clawing the access back is the hard part. The agent is not waiting for your ticket queue. It is making requests now.

There is a second, quieter problem. Short expiry does not rescue you. NIST and CISA finalized Interagency Report 8587 on September 15, 2026, recommending that access and identity tokens live no more than an hour. Good advice, and the AgentCore case from earlier this month shows its limit. Those credentials were temporary. They expired on schedule. While alive, the default role behind them reached every agent in the account and region, so a single prompt to one public agent returned credentials that could launch other agents, read their sessions, and pull secrets. A 60-minute token with account-wide reach is not a small risk. It is a one-hour window with a very large room inside it.

Expiry bounds how long a stolen credential lives. Revocation decides whether it lives another minute. You need both, and only one of them works during an incident.

Build Revocation Into the Token, Not Around It

The design that passes the timed test has four parts, none of them exotic.

First, one identity per agent, issued per agent, never borrowed from a human or a sibling workload. Second, a token that names that identity and its scopes, with an expiry of an hour or less. Third, a revocation check on every request, not a cache you hope is fresh. Fourth, a kill operation scoped to one agent ID, callable by a named owner, that takes effect on the next request rather than the next deploy.

Here is the whole mechanism in standard-library Python. It is small on purpose. If your revocation path needs a console, a ticket, and a prayer, the size of this file is the argument.

import time, secrets

TTL = 900  # 15 minutes. IR 8587 says an hour or less; shorter is fine.

class TokenService:
    def __init__(self):
        self.tokens = {}    # token_id -> {agent, scopes, expires}
        self.revoked = set()  # token_ids killed now, checked per request

    def issue(self, agent, scopes, ttl=TTL):
        tid = secrets.token_hex(8)
        self.tokens[tid] = {
            "agent": agent,
            "scopes": set(scopes),
            "expires": time.time() + ttl,
        }
        return tid

    def revoke_agent(self, agent):
        killed = 0
        for tid, t in self.tokens.items():
            if t["agent"] == agent and tid not in self.revoked:
                self.revoked.add(tid)
                killed += 1
        return killed

    def check(self, tid, scope, now=None):
        now = now or time.time()
        if tid in self.revoked:
            return "DENY revoked"
        t = self.tokens.get(tid)
        if not t:
            return "DENY unknown"
        if now > t["expires"]:
            return "DENY expired"
        if scope not in t["scopes"]:
            return "DENY scope"
        return "ALLOW"
Enter fullscreen mode Exit fullscreen mode

A few things are worth noting about this example. First, revoke_agent takes an agent name, not a token ID. In an incident you know which agent is misbehaving. You may not know, or want to hunt for, every token it holds. The operation should match the knowledge you actually have at 2 a.m. Second, the revocation set is consulted before expiry and before scope. A revoked token fails even if it has 14 minutes of life left and a perfectly valid scope. Precedence is the policy. Third, there is no rotation step hidden inside the kill. Revoking research does not reissue anything to billing. The blast radius of the response is one agent, which is the whole point.

Run it through the three situations that matter:

=== Scenario 1: one shared token for two agents ===
research agent: ALLOW
billing agent:  ALLOW
research agent is compromised. Revoke the shared token.
research agent: DENY revoked
billing agent:  DENY revoked   <-- collateral damage

=== Scenario 2: one token per agent ===
research agent: ALLOW
billing agent:  ALLOW
revoked 1 token(s) for research
research agent: DENY revoked   <-- dies on its very next request
billing agent:  ALLOW          <-- untouched

=== Scenario 3: revocation vs waiting for expiry ===
a fresh token has 900 seconds of life left
without revocation, a stolen copy stays valid for all of it
after revoke_agent: DENY revoked
  <-- effective time to kill: 0 seconds, not 900
Enter fullscreen mode Exit fullscreen mode

Scenario 1 is not a straw man. It is the configuration 45 of 102 survey respondents described, in whole or in part. Notice that nothing in scenario 1 is misconfigured in the usual sense. The token works. The scopes work. The failure only appears when you ask the system the incident question, and by then the question is urgent.

Place the Check Where It Cannot Be Skipped

In production, the in-memory set above becomes one of three real homes, and the choice is a latency and consistency trade you should make on purpose.

Put the revocation list in the same store your gate already reads, and the check costs what your existing policy check costs. Redis is the common pick:

# Kill every token for one agent, from the incident channel, no deploy
redis-cli SADD revoked:agents research-agent
redis-cli EXPIRE revoked:agents 3600

# The gate, on every request, before it evaluates scope
redis-cli SISMEMBER revoked:agents research-agent
Enter fullscreen mode Exit fullscreen mode

A result of 1 means deny, full stop, whatever the token says. Set the entry to expire after your longest token lifetime, because once every token that agent ever held has expired, the revocation entry has done its work and can age out.

If your agents call cloud APIs directly, the equivalent move lives in IAM rather than in your gate. Tag sessions with the agent ID when the role is assumed, and deny by that tag:

aws iam get-role --role-name agent-research
aws sts get-session-token --duration-seconds 900
# Incident step: attach an inline deny keyed on aws:PrincipalTag/agent
aws iam put-role-policy --role-name agent-research \
  --policy-name kill-research --policy-document file://deny.json
Enter fullscreen mode Exit fullscreen mode

And keep the witness running before you need it. A revocation you cannot verify is a rumor. Your audit log should record the kill, the owner who called it, and the first denied request after it. That denied request is your proof that the control worked, stamped by the system rather than asserted in a postmortem.

Here is the pipeline, end to end:

  request --> [revoked?] --yes--> DENY, log it, done
                  |
                  no
                  v
             [expired?] --yes--> DENY
                  |
                  no
                  v
             [scope fits?] --no--> DENY
                  |
                  yes
                  v
                ALLOW, log it

  kill path:  owner -> revoke(agent_id) -> revocation store
              (takes effect on that agent's next request)
Enter fullscreen mode Exit fullscreen mode

The order in that diagram is deliberate. Revocation first, because it is the only check whose answer changes during an incident. Expiry and scope are static properties of the token. Revocation is a live decision by a human or an automated detector, and live decisions should outrank static ones.

Run the Timed Test This Week

Do not take this on faith, and do not take your architecture diagram's word for it either. Run the test the survey points at. Pick one low-stakes agent. Announce it if your team needs warning. Then revoke, and measure three things: time from decision to first denied request, number of other agents affected, and number of systems you had to touch to do it.

Write the numbers down where the next incident responder will find them. If the time is measured in hours, or the affected count is above one, or the systems touched include a secrets manager, a deploy pipeline, and someone's personal knowledge of which key is which, you have found the work. It is not a tooling purchase. Per-agent issuance, a per-request revocation check, and a named owner with a working kill path will get most teams from hours to minutes with components they already run.

Scoping decides what an agent may do on a good day. Revocation decides what happens on the bad one. Only the second answer matters during an incident.

Where This Breaks

  • The revocation check is itself a dependency. If the store holding your revocation list is down, decide in advance whether the gate fails closed (agents stop, business stops) or fails open (agents run, revocation is decorative). Write the choice down before the outage picks it for you.
  • Revocation kills future requests. It does not undo work the agent already completed, recall data it already sent, or unwrite memory it already stored. Pair the kill with a review of what the agent touched during the window it was live.
  • Agents with work in flight will fail mid-task. A killed agent holding a half-finished multi-step job leaves partial state behind. Your kill path needs a companion answer for draining or compensating in-flight work, or you will hesitate to use it when it matters.
  • Long-lived connections hide from per-request checks. A token revoked while an agent holds an open stream or a pooled connection may keep working until that connection cycles. Check on reconnect as well as on request, and cap connection lifetimes.
  • The kill switch is a privileged operation, so it becomes a target. Whoever can revoke every agent can cause the outage themselves. Scope the permission, log every use, and require a second pair of eyes for revoking more than one agent at a time.

Decide Whether You Need This

Build it if:

  • More than one agent shares any credential today, for any reason, including "just for now"
  • Your honest timed answer for revoking one agent is over 15 minutes
  • One agent's role can reach another agent's sessions, memory, or secrets
  • You learned how your agents authenticate by asking around, which puts you in the survey's 22

Skip it if:

  • You run one agent, on your own machine, with a credential that reaches nothing you care about
  • Every agent already has its own identity, sub-hour tokens, and a kill path you have timed in a drill this quarter

The minimal viable version fits in an afternoon. Per-agent tokens from the code above, the revocation check placed in front of the scope check you already have, one named owner, and one timed drill. Add the Redis or IAM layer after the drill tells you where the minutes actually went.

Close the Loop Before the Incident Does

Stop auditing how your agents get access and start timing how they lose it. Issue per agent, check revocation on every request, name the owner, and run the drill while the stakes are a mildly annoyed colleague instead of a postmortem. Fourteen of 102 enterprises could revoke in minutes. There is no technical reason your team cannot be the fifteenth.

When you ran your last revocation drill, or your last real kill, how long did it actually take, and what surprised you?

Resources

  1. VentureBeat: 17 of 40 teams that say they enforce AI agent permissions still share the credentials behind them
  2. Your agent should not borrow your API key, on scoped, expiring credentials per agent
  3. One prompt took over every agent in the account: the default role is the blast radius

Top comments (1)

Collapse
 
mickyarun profile image
arun rajkumar •

The timed test measures the easy direction. "Its next request fails" is the clean case, where the agent is idle when you pull the key. The drill I'd add is killing it mid-call, because that's the one you'll be doing — you revoke when something is going wrong, which is when it's busiest.

Your third bullet under Where This Breaks is the right one and I'd make it harder. In payments the cost of a mid-flight kill isn't partial state, it's an unknown. Kill the agent after it has sent the instruction and before it has recorded the response, and neither your record nor its record says whether the money moved. Compensation needs to know what happened. Revocation is the exact moment you lose the ability to ask the thing that knew.

So the precondition for a fast kill isn't in the kill path at all. Every irreversible call the agent can make has to carry an idempotency key you chose, and be queryable by someone other than the agent, before you ever need it. Then after the kill you ask the counterparty what they saw. Without that, a four-minute revocation buys you a fast stop and a slow reconciliation, and the reconciliation was always the expensive half.