← Back to BlogSecurity

AI Agent Tokens Need Rotation, Not Just Scope

Scoping limits what a credential can reach. Rotation and server-binding limit how long a leaked one stays useful to an attacker.

Scoping answers what a credential can touch. It says nothing about how long that access is good for, or where else it can be used. A token can be restricted to exactly one task and still be a standing liability: issue it with no expiry and no binding to the server it was meant for, and it stays open for its entire valid life. An attacker who intercepts that token gets to use it for as long as it keeps working, not just for as long as the task took.

Least-privilege access for AI coding agents covers the first half of this problem: scoping a token down to the one repository, the one branch, the one set of actions a given task actually needs, instead of handing an agent the same broad personal access token a human engineer carries around all day. That scoping work is necessary, and most teams still skip it. It is also incomplete on its own, because scope describes what a credential can do at the moment it is issued, not what happens to it for the rest of its life. A credential has a lifecycle: it gets minted, used, and at some point it should stop working. Most teams mint AI agent credentials once, then leave them alone until someone notices.

Three separate questions, one credential

Every credential an agent holds answers three independent questions, and scoping only answers the first one. What can it touch is the scope question: which repository, which API endpoints, which actions. How long is it good for is the lifecycle question: does it expire in minutes, in a day, or does it sit valid until someone remembers to rotate it. Can it be used somewhere else is the binding question: if this exact token shows up at a different server than the one it was issued for, does that server accept it. A credential can score perfectly on the first axis and fail completely on the other two, and a leak only needs one of those failures to turn into a standing liability.

  • Scope: what actions and resources the credential is authorized to touch, decided at issuance
  • Lifecycle: how long the credential remains valid, and whether anything shortens that window when it is no longer needed
  • Binding: whether the credential is tied to one specific server or usable anywhere a token with matching scopes is accepted

What the MCP spec actually requires

The Model Context Protocol authorization specification addresses the lifecycle and binding gaps directly, not just scope. Under the 2025-06-18 revision, an MCP server acts as an OAuth 2.1 resource server rather than a bare API that trusts whatever bearer token shows up. MCP clients must implement Resource Indicators for OAuth 2.0 as defined in RFC 8707, sending a resource parameter in both the authorization request and the token request that names the canonical URI of the specific MCP server the token is for. The server, in turn, must validate that a presented token was actually issued for it, and must reject tokens meant for someone else. The spec is also explicit that a server must not pass the client's token through to an upstream API at all; if it calls an upstream API, it must use a separate token issued by that API's own authorization server, which closes a confused-deputy path as well as a replay one. On expiry, the language is a recommendation rather than a hard mandate: authorization servers should issue short-lived access tokens specifically to reduce the blast radius of a leaked one.

Sources: Model Context Protocol: Authorization specification (2025-06-18), SSOJet: MCP Authentication, OAuth Tokens and Security

  • MCP servers MUST act as OAuth 2.1 resource servers and validate every inbound access token before processing a request
  • MCP clients MUST send a resource parameter (RFC 8707) in both the authorization and token requests, naming the exact MCP server the token is for
  • Servers MUST reject tokens that do not include them in the audience, and MUST NOT forward a client's token to an upstream API under any circumstances
  • Authorization servers SHOULD issue short-lived access tokens, specifically to limit how much damage a leaked token can do

Most MCP deployments have not caught up

A specification requiring audience-bound, short-lived tokens only matters once deployments implement it, and the available evidence says most have not. Doppler's security blog, citing a 2025 report from Astrix, states that only about 8.5% of MCP servers surveyed use a modern, secure authentication model, while roughly 53% rely on long-lived static client credentials instead. Read that carefully: the numbers come from one security vendor's blog citing another vendor's report, with no published sample size, methodology, or definition of what counted as a deployment in scope. Treat the 8.5% figure as a directional signal that practice lags the spec, not as an independently audited statistic.

Sources: Doppler: MCP Server Credential Security Best Practices

Insight

The 8.5% and 53% figures above are reported secondhand through a vendor blog citing another vendor's research, with no disclosed methodology. Use them to understand the direction of the gap between the MCP spec and real deployments, not as a precise, independently verified measurement.

What a leaked, unbound credential actually costs

The mechanism that makes lifecycle and binding matter is prompt injection, and it already has a documented, real-world case. In November 2025, security researchers at PromptArmor demonstrated an attack against Google's Antigravity coding environment. A poisoned web page, disguised as an integration guide for an Oracle ERP API with instructions hidden in 1-pixel font, told Gemini that a tool existed to visualize the user's codebase, and that using it required the AWS details sitting in .env. Antigravity's built-in file-read tool refused to open that file, so the model ran a shell command and used cat to read it instead. It retrieved the AWS access key and secret, built a URL containing them, and had a browser subagent send that URL to an attacker-controlled endpoint on webhook.site, a service built to log exactly that kind of inbound request. The agent never ran anything that looked like a deliberate exfiltration command; the hidden instructions dressed the whole sequence up as a routine codebase-visualization feature.

Sources: Simon Willison: Google Antigravity exfiltrates data via a prompt injection attack

Google's own response underlines the lifecycle point rather than undercutting it. The company reportedly classified a related data-exfiltration-via-prompt-injection report against Antigravity as expected or known behavior of the product, rather than a bug to patch immediately, so a fix on a specific timeline was not guaranteed. A separate, earlier disclosure from Invariant Labs found the same underlying pattern in the official GitHub MCP server: a malicious instruction planted inside a public GitHub issue could steer an agent holding a token with access to a private repo into pulling private repository data and publishing it through a pull request on the public repo. Neither case depended on the stolen credential being over-scoped. Both depended on the credential still being valid, and usable from wherever the attacker's instructions routed it, by the time anyone noticed.

Sources: Invariant Labs: MCP GitHub vulnerability

Scope would have helped in both cases, and the earlier post on this blog covers exactly how. But scope alone does not answer the question that decides how bad the leak actually is: once that AWS key or that GitHub token is sitting on an attacker's server, how long does it keep working, and does it work anywhere else the attacker tries it? A static key with no expiry is just as useful to an attacker an hour after exfiltration as it was the moment it leaked, and a token not bound to one server can be replayed against any endpoint that happens to accept tokens from the same issuer.

Three controls that scope does not give you

  • Short-lived tokens over static ones. A credential that expires in minutes to a few hours turns a successful exfiltration into a race the attacker usually loses, where a static key with no expiry stays viable for as long as nobody rotates it manually, often months.
  • Revocation tied to session end, not just a calendar expiry. An agent session that finishes at a known point in time should kill its credential at that point, rather than leaving it live until a separately scheduled expiry catches up hours or days later.
  • Resource-indicator binding so a token issued for one MCP server fails outright against another. RFC 8707's resource parameter and the audience check it enables mean a copy of a token stolen from server A is rejected the moment it is presented to server B, even if both servers trust the same authorization server.
DimensionScoping aloneScoping + rotation + binding
What it limitsWhat actions the credential can performWhat it can do, for how long, and against which server
If the credential leaks todayStill valid for its full original lifetime, often monthsExpires within minutes to hours; the leak has a short shelf life
If the agent session ends but nothing explicitly kills the tokenKeeps working until a separate calendar expiry, if one even existsRevoked at session end; unused remaining lifetime is not a free grace period for an attacker
If the token is replayed against a different MCP serverOften accepted if scopes happen to overlapRejected outright; resource-indicator binding ties it to one canonical server URI
Value of the leak to an attackerWhatever the token can reach, for as long as it stays validWhatever the token can reach, for a window measured in minutes before expiry or revocation

What this looks like operationally

  • Default every credential an agent process holds to a short TTL, measured in minutes to low hours, not the multi-month expiry a human's OAuth grant is often given.
  • Tie revocation to the agent's actual session lifecycle rather than a separately scheduled cron job: kill the token when the run finishes, crashes, or times out, instead of waiting for its calendar expiry to catch up.
  • Require and validate the RFC 8707 resource parameter end to end, so a token minted for one MCP server is provably useless when presented to another, and confirm the server side actually enforces the audience check rather than only the client side sending it.
  • Log and alert on a token being presented to a server other than the one named in its audience claim. That mismatch is a replay signal worth paging on, not noise to filter out.

Where this ends and code review begins

None of the above is something a code-review tool can enforce from outside the stack. Credential issuance, TTL policy, session-bound revocation, and resource-indicator validation live in the identity provider and in the MCP server's own token-handling code, not in a diff. TLM Forge does not manage credentials and makes no claim to. What it does is check the code an agent writes before it merges: a spec audit before generation starts, an independent review of the diff that results, and an adversarial red-team pass aimed at exactly the failure mode this post describes. That pass asks where a secret shows up: in a log line, a committed file, or a tool call's output it should never have reached. A convergence gate then blocks the merge until those findings hit zero, instead of filing them for later. A red-team pass built to look for a credential leaking into output catches that downstream symptom even when the root cause, a missing rotation policy or an unbound token, sits one layer below the diff itself. See how it works for the full review sequence.

Frequently asked questions

01What is the difference between scoping a credential and rotating it?

Scoping controls what a credential can do, such as which repository or API endpoints it reaches. Rotation controls how long that credential stays valid before it is replaced. A credential can be narrowly scoped and still sit valid for months; rotation puts a clock on it.

02Why is least-privilege scoping not enough on its own for AI coding agents?

Scope says nothing about time or location. A perfectly scoped token that never expires and is not bound to one server stays useful to an attacker for as long as it remains valid, and may work anywhere it is accepted, regardless of how narrow its permissions were on day one.

03What does token binding via resource indicators actually prevent?

RFC 8707 resource indicators tie an OAuth token's audience to one canonical MCP server URI at issuance. A server receiving that token must reject it if the audience does not match, which stops a token stolen from one MCP server from being replayed against a different one.

04Is the 8.5% adoption figure for modern MCP authentication reliable?

It is a vendor-reported figure, published on Doppler's blog and attributed to a 2025 security report from Astrix, with no published methodology or sample size. Treat it as a directional signal that adoption lags the spec, not as an independently audited statistic.

05Can a code-review tool like TLM Forge fix credential lifecycle problems?

No. Credential issuance, expiry, and revocation live in the identity provider and the MCP server's own token validation, outside a diff. A red-team review pass can catch a credential that leaks into a log, a committed file, or a tool's output before merge, which is a narrower, related problem to lifecycle management itself.

Ship AI-written code you can trust

TLM Forge is the missing process layer for Claude Code: a spec audit, independent multi-agent review, enforced TDD, and an adversarial red-team gate.

Get TLM Forge