Credential lifetime.
Once a credential has been copied off a machine, exactly one of its properties is still yours to control, and it is not the scope — it is how long the thing keeps working. That is why the short access-token TTL you are proud of usually buys nothing: in the agent tooling people actually run, the short-lived token sits in the same file as a refresh token good for weeks, and a refresh is renewal without re-authentication. The number to measure is not your token's TTL. It is the wall-clock gap between someone took this and this stopped working.
Lifetime is the only control that still applies after the theft.
Walk the controls in a normal credential design and ask which ones survive a copy. Scope survives, in the sense that it still bounds the damage — but it bounded the damage before the theft too, and it did not change. Audience restriction, mTLS binding and attestation are the interesting exceptions, and almost nobody has them on a developer workstation. Everything else — the approval that issued the token, the policy that justified it, the review that signed off on it — happened before the copy and has no further effect.
- Lifetime is the one term with a clock in it. Every other control is evaluated once, at issuance. Lifetime keeps being evaluated, by someone else's infrastructure, for as long as the credential is alive.
- It is the term that converts a breach into an interval. "An attacker had our agent's credentials" is unanswerable. "An attacker had them for nineteen minutes, and here is what was reachable in nineteen minutes" is an incident report.
- It is also the term you are most likely to have set by accident. Scope gets argued over in review. Lifetime is usually whatever the SDK's default was, and nobody has looked at it since.
This is the per-credential version of the argument in blast radius. Blast radius asks how far a compromise reaches; lifetime asks how long it keeps reaching. Multiply them and you have the actual exposure — and teams routinely shrink the first by a factor of ten while leaving the second at thirty days.
A refresh token next to an access token sets the real lifetime.
The standard pattern is an access token with a lifetime measured in minutes to an hour, plus a refresh token that mints new ones without the user reappearing. Each half is defensible. Stored together, as a pair, in one file, the pair's lifetime is the refresh token's — and anyone holding both can keep the short-lived half permanently fresh. The access token's TTL has stopped being a security property and become a latency property.
You can read the arithmetic off a shipping product. Anthropic's Claude Code keeps its login in ~/.claude/.credentials.json at mode 0600 on Linux, and a September 2026 report against the project records the file holding a live access token alongside a refresh token valid for twenty-seven days. One-hour access tokens, twenty-seven-day exposure, and the difference is a single additional JSON key. Nothing here is unusual or careless by the standards of the field — that is the point. It is the normal shape.
- Ask what the pair is worth, never the token. The right question in a design review is "if this directory is copied, how long does the copy work" — not "what is our TTL".
- Refresh without re-auth is renewal without a decision. If no human, device check or attestation participates in refresh, then nothing in the loop can notice that the renewer changed.
- File mode is not a lifetime control, and not much of an access control. Mode
0600stops a different user on the same host. Credential-stealing malware runs as you — see agent artifacts on the endpoint. - Bind refresh to something, if you can bind anything. Device-bound or sender-constrained refresh is the one change that makes a copied pair less than fully portable; agent identity and attestation covers the mechanics.
Short lifetimes are not free, and the bill lands somewhere specific.
The reason credentials live long is not that nobody thought about it. It is that every reduction in lifetime is paid for by someone, and the three bills are predictable. Pretending otherwise produces the familiar outcome where a team mandates one-hour tokens, discovers the cost, and quietly issues a service account with no expiry at all.
- Re-authentication friction. Interactive logins land on a human. If your rotation interval is shorter than the human's attention span, they will automate around you, usually by pasting a long-lived key into an environment variable.
- Outage amplification. A short lifetime makes the issuer a hard dependency of every run. If the token service is down for twenty minutes and your tokens live five, your agents are down too. That is a fail-closed choice, and it is often the right one — but choose it deliberately.
- Long-running work. An agent run that outlives its own credential fails in the middle, which is the worst place, because the side effects are half-applied. This is why deadline budgets and credential lifetime have to be designed as one number, not two.
The way out is to stop treating lifetime as a global setting. A credential minted for one task, valid for that task's deadline plus a margin, costs nothing in friction because no human is in the loop, and costs nothing in outage amplification because it is acquired once at the start of a run rather than refreshed throughout it.
Measure time-to-revoke, because that is the number you will be asked for.
Lifetime has a twin that most teams have never timed: revocation. A thirty-day token with a revocation path you can execute in two minutes is a better credential than a one-hour token you cannot kill at all — and the second case is common, because stateless bearer tokens are valid until expiry by construction, with no list to add them to.
- Run the drill, once, with a stopwatch. Pick a real agent credential, revoke it, and record when the next call using it actually failed. Most teams learn two things: they did not know who could perform the revocation, and the effect was not immediate.
- Know which of your tokens are revocable at all. Introspected or reference tokens can be killed centrally. Self-contained JWTs cannot, unless you built a denylist and every verifier checks it. Write the list down per credential type.
- Count the copies you will need to kill. One agent credential is often present in a secret store, a CI environment, two developer laptops and a trace. Revocation that misses a copy is not revocation; access reviews for agent credentials is about keeping that list honest.
- Put the revocation trigger next to the detection. A detector that pages a human adds the human's response time to your exposure window. If the finding is unambiguous — a honeytoken touch, a token used from a new region — wire it to the revocation call directly.
Do this in order. First, for your highest-privilege agent credential, write down the lifetime of the pair rather than the access token — if a refresh token is involved, that is your real number, and it is probably weeks. Second, time one revocation with a stopwatch and record who performed it. Third, move that credential's issuance to per-run with a lifetime set from the run's deadline. The first two cost an afternoon and will change what you prioritise; the third is the actual fix.
Related: ambient authority for why the credential was reachable without anyone asking, scoped credentials for agents for the other axis of the same object, and configuration as reconnaissance for what else an attacker gets out of the file the credential was sitting in.