Short-lived credentials for AI agents: leasing instead of handing out keys
Per-task, expiring credentials and the mechanics behind them: AWS session policies and credential_process, OIDC for CI, and where a lease has to come from when the agent runs on a laptop. Includes the bootstrap problem, which is the part teams miss.
A short-lived credential for an AI agent is one issued for a single task, scoped to the few actions that task needs, and expired before anyone could reuse it. The goal is that a token leaked into a transcript, a log line or a pasted error message is worthless in minutes rather than valid for months.
Most teams already believe this. The gap is mechanical: an agent on a laptop has no natural place to get a lease from, so it inherits whatever is on disk.
What the agent is holding today
| Location | What it holds | Lifetime |
|---|---|---|
~/.aws/credentials | Long-lived access key | Until someone rotates it |
~/.ssh/id_ed25519 | Private key, often unencrypted | Years |
.env in a project | API keys, database URLs | Until someone rotates them |
mcp.json env block | Keys pasted so the server can start | Same as above |
| Shell environment | Whatever the parent process exported | The session |
| CI secrets | Repository or organisation secrets | Until rotated, masked in logs |
Every one of these is a bearer credential. Anyone who reads it can use it, and the audit trail shows the key, not the person.
Three shapes, one direction of travel
| Shape | How the agent gets it | Typical lifetime | Blast radius | Revocation |
|---|---|---|---|---|
| Standing key on disk | It was provisioned once | Months | The account or key's full permission | Rotate everywhere it was copied |
| Assumed role, fetched on demand | A helper exchanges a stronger identity for a scoped session | 15 minutes to 12 hours | The role's policy and the session policy | End the session |
| Brokered lease | A broker checks a policy, issues it, injects it at the moment of use | Minutes | One operation, one target | Expiry, with revocation as the fallback |
The direction is the same in all three columns: less standing authority, more per-request authority, and a shorter window in which a mistake is expensive.
What the clouds give you, and the limits
AWS Security Token Service issues temporary credentials through AssumeRole. DurationSeconds ranges from 900 seconds to 43,200, defaults to 3,600, and cannot exceed the role's MaxSessionDuration; a session assumed from another role's credentials (role chaining) is capped at one hour (temporary credential requests). The session policy is the part worth using: pass a policy that allows one bucket prefix and nothing else, so a wide role cannot be used wide.
The AWS CLI and every SDK can fetch those credentials themselves through credential_process, a program named in the profile that prints JSON to stdout (sourcing credentials). That is the seam where an agent gets a fresh, small credential without a file on disk:
# ~/.aws/config
[profile agent-readonly]
region = us-east-1
credential_process = /usr/local/bin/agent-credential --profile agent-readonly
The helper prints this and nothing else:
{
"Version": 1,
"AccessKeyId": "ASIAEXAMPLE",
"SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"SessionToken": "IQoJb3JpZ2luX2VjEXAMPLESESSIONTOKEN",
"Expiration": "2026-11-03T14:15:00Z"
}
Three details decide whether the helper is a control or a liability. It caches the JSON in memory until five minutes before Expiration and refreshes instead of writing a credentials file. It exits non-zero when it cannot get a session, so the caller fails closed rather than running unauthenticated. And the identity it uses to assume the role is itself short-lived, which is the hard part (more on that below).
Outside AWS the shape repeats. GitHub Actions can mint an OIDC token per job with permissions: id-token: write and exchange it for cloud credentials, with no stored key (configure-aws-credentials, GitHub OIDC). Google Cloud has workload identity federation, and Azure has workload identity federation for the same exchange (Google, Microsoft). On a workstation, the equivalent trusted identity is the device itself.
Where short lifetimes stop helping
- The bootstrap credential. A helper that assumes a role has to authenticate as something. If the answer is a long-lived key in
~/.aws/credentials, the lease has moved the problem one step and left a key on disk to get it. - The agent can read the helper. A script that holds a secret to trade for a lease is a file an agent can open if it runs as the same user.
- Inheritance. An agent that starts a subprocess passes its environment along, so a credential in
AWS_SECRET_ACCESS_KEYreaches a plugin, a build script or an MCP server without anyone opening a file. - The window. Fifteen minutes is a real improvement over fifteen months and still fifteen minutes of exfiltration if the agent can send what it read.
- Logs. A short-lived token printed to a terminal ends up in a transcript or a CI log. Expiry makes that survivable; redaction makes it rare.
- Revocation. Expiry is not revocation. An incident at minute two needs a way to kill a session before its timeout, and providers differ on how fast that takes effect.
The residual risk after a lease is the read-then-send pair: the agent reads a secret it is entitled to and sends it somewhere it should not. Lifetime does not fix that, which is why the sequence rule in the policy post exists.
The lease, with the grant attached
Alyria's secrets layer, Umbra, issues secrets to agents as short-lived leases instead of storing credentials on the endpoint. A Lyra capability grant is what authorises the lease, so the credential and the reason for it travel together:
{
"lease": "lease.7Q2f...",
"path": "db/prod/credentials",
"granted_by": "alyria.lyra/allow.etl-role",
"ttl_seconds": 300,
"custody": "byok"
}
The agent asks for the secret and the broker answers only if the policy allows that identity to use it:
umbra get db/prod/credentials --as agent:etl-worker
Alyria Beacon injects the lease into the request at the moment of use and discards it afterwards, so the plaintext is not written into the agent's context, its shell history or a config file. Leases expire and rotate, and every issuance and use lands in the signed audit chain, which answers the question a standing key cannot: which agent used which credential, under which grant, at what time.
For secrets that have to be consumed on the endpoint, Umbra seals each one to the device's own hardware key, a TPM or a Secure Enclave, certified by the tenant root, and the broker only moves ciphertext. Enterprises can hold their own KMS key, or one Alyria never sees, and revoke it.
A rollout order that survives the first sprint
- Inventory where credentials sit today, starting with MCP config files that carry inline
envkeys. That list is usually longer than the team expects. - Move the five credentials with the widest reach to leases first: cloud admin, package registry publish, production database, source control, and the secret store's own token.
- Set the shortest lifetime the workflow tolerates and measure the failure mode. Most refresh problems show up as a 403 at the wrong minute, not as a leak.
- Make the refresh path fail closed, and give on-call a documented break-glass credential with its own rotation.
- Add the read-then-egress rule for whatever is left, because step 2 will not reach every long-lived key in the first quarter.
- Keep the record. A lease with no audit entry is a shorter-lived version of the same blind spot.
What to say when someone asks for the key
The useful answer is that there is no key to send. There is a grant, a lease that expires in five minutes, and a record of the exchange. That answer also removes the question that stalls most rollouts, which is where the new standing credential would be stored.
More detail on custody and hand-offs is on Umbra, secrets under your keys, and keeping coding agents away from .env files covers the endpoint controls that stop the read. Cloud and provider behaviour above comes from the AWS IAM, AWS CLI, GitHub, Google Cloud and Microsoft documentation read in November 2026; check the current session duration limits and revocation behaviour before you set a lease lifetime.
Try it with Alyria
Replace one standing key with a lease and watch the grant, the TTL and the use land in the audit chain. Start with the credential with the widest reach, which on most laptops is the cloud key in ~/.aws/credentials. Start free and move that one key first.