Skip to main content
All writing
Capability Lease · 1/3
11 min read

The Capability Lease

Long-lived credentials are the SQL injection of the agent era.

In 2008 we figured out that string-concatenating user input into SQL was a class of bug. We named it. We taught it. Now we parameterise. The category didn't disappear — it became unfashionable. Anybody shipping concatenated SQL in 2026 is doing something that 18 years of working engineers have collectively rolled their eyes at.

AI agents in 2026 are doing the 2008 equivalent every single hour. We give them long-lived API keys with broad scopes and trust that an autonomous loop, fed from a probabilistic model, fed from internet-shaped data, will not do anything stupid. We are surprised every time it does.

An AI agent does not need an API key. It needs a capability lease.

What a capability lease is

A capability lease is a short-lived, narrowly-scoped, revocable proof that this specific agent — identified by a non-human identity (NHI) — is allowed to perform this specific action against this specific resource right now. Four properties matter:

(1) Short-lived. Lifetime measured in seconds-to-minutes for sensitive actions, hours for routine ones. Long enough to finish the task. Short enough that a leaked lease has nearly no half-life.

(2) Scoped. The lease names the operation, the resource, and the bounds. Not "can write to S3." "Can PUT to s3://bucket-x/agent-{id}/* with content-type image/* up to 5 MB until T+90s." The narrower the verb, the smaller the blast radius when the agent gets prompt-injected next Tuesday.

(3) Revocable. The issuer can kill an outstanding lease in O(1) — every consumer checks a revocation surface that's cheap to update. Long-lived keys are revocable in principle and unrevocable in practice; the operator never knows which key was where. Capability leases invert that default.

(4) Attributable. Every lease ties to an NHI ties to an agent run ties to a human or workflow that authorised it. The audit trail isn't bolted on later. The lease is the audit trail.

Why this isn't OAuth

OAuth solves a related problem — delegating human-scoped access to a third-party app. The OAuth bearer token is the human's lease. It's still long-lived by agent standards (an hour, sometimes a day). It's still scoped to the user, not to a specific autonomous run. And it's almost never revoked in the moment that matters.

Capability leases are downstream of OAuth, MCP authentication, and the emerging NHI stack — they take whatever first-class identity the human delegated, and mint per-run, per-action sub-credentials that exist for the duration of the agent's actual work.

The three layers that converge here

The reason this name needs to exist now — not in 2028 — is that three independent vendor moves in 2026 all converge on the same shape:

Directory — Okta for AI Agents (GA April 2026)

Non-human identities live in the same Universal Directory as humans. The agent is a named, lifecycled, audit-traced principal. NHI tokens carry the proof of who's running.

Cryptographic identity — Cisco Agentic Workforce Identity (RSAC 2026)

Agents present cryptographic claims. The network layer knows who's talking before the application layer does. SPIFFE/SPIRE-shaped identities for the agent fleet.

Per-call authorisation — Cloudflare Mesh

Every call between agents (and between agents and tools) is gated by a per-call policy decision. Not a session, not a token-with-broad-scope — a per-action proof.

Capability lease is the lingua franca for the third layer. The vendors don't all call it that yet. They will. Or someone else will name it first and the field will cite them.

What it looks like on the wire

A working capability-lease envelope, roughly the shape I use in agent-airlock + agent-audit-kit (this is wire-format pseudocode, not a spec):

{
  "agent_nhi": "okta:nhi_01HX...",          // who
  "run_id": "run_01HY...",                  // why (this run, not the session)
  "action": "write",                        // verb
  "resource": "s3://bucket-x/agent-01HX...", // noun
  "constraints": {                          // bounds
    "max_bytes": 5242880,
    "content_type_glob": "image/*"
  },
  "issued_at": 1716470000,                  // when
  "expires_at": 1716470090,                 // 90 seconds from now
  "issuer_sig": "ed25519:...",              // proof
  "revocation_url": "https://...",          // kill switch
  "audit_emit": "https://audit.example/..." // where this lease's use is recorded
}

The token is the contract. The token is the audit row. The token is the kill switch. There is no "the agent has the keys, hope it doesn't misuse them."

Why this matters for security tooling

I ship agent-audit-kit, an open-source SAST scanner for agentic systems. One of the rule families it ships (AAK-CAPLEASE-*) detects when an agent receives a long-lived secret at a tool-call boundary where a capability lease would be the correct pattern. That rule is fine. The rule isn't the point.

The rule isn't the point. The vocabulary is the point.

If "capability lease" doesn't get named, every team rebuilds the pattern from scratch, badly, in private. If it does get named, the lazy version of "don't ship long-lived keys to agents" becomes a default, the way parameterised queries became a default. The lazy default is the win — the lazy default is what 95 % of teams ever actually do.

We don't need brilliant agent operators. We need a vocabulary that turns the right move into the lazy move.

What's next in this series

Essay #2: "How Okta NHI + Cisco AWI + Cloudflare Mesh all converge on capability leases" — concrete mapping across the three vendor stacks, what each gives you, where the gaps are.

Essay #3: "Implementing capability leases in MCP" — working pattern from agent-audit-kit's rule family AAK-CAPLEASE-001, the wire format above, and the runtime enforcement story via agent-airlock.

Or: if you'd rather read those when they ship, subscribe to The Production Agent — link below.

References