Classic painting used as the article cover
← Back to blog

WORKLOAD IDENTITY

Workload Identity for Agents: SPIFFE, SVIDs, and the End of Long-Lived Keys

SPIFFE gives a workload a cryptographic identity with no secret to steal. Here is how SVIDs, attestation and trust-domain federation work, and why they answer only half the question an agent raises.

•Sep 11, 2026•15 min
Workload IdentityIdentityZero Trust

TL;DR

Most teams running a handful of agents don't need to stand up SPIRE. They need to stop reusing one API key across three environments, which is a far smaller project.

GitGuardian counted 28.65 million hardcoded secrets added to public GitHub in 2025, and found that 64% of the secrets flagged back in 2022 were still live in 2026. Possession-based credentials produce exactly that at scale, and SPIFFE solved the underlying problem for services a decade before agents existed.

We think people conflate two separate decisions: whether to give every workload an attested identity, and whether to run SPIRE specifically. A signing server, a per-node agent, and a registration-entry lifecycle are real operational weight, and GKE Workload Identity Federation, EKS Pod Identity, and Entra Workload ID already deliver most of the same properties with nothing new to operate.

Adopting workload identity matters regardless of which implementation you pick. What it doesn't answer, even in SPIRE's full form, is who an agent is acting for, and that needs a second, separate layer. Start with your cloud's native federation, and reach for SPIRE only once you're crossing trust domains it can't reach.

Overview

An agent runs as a process. Before it's a reasoning loop or a tool-calling policy, it's a workload on a host, in a container, in a cluster, in an account. The question of how that workload proves what it is has an answer that predates agents by a decade, and most agent deployments aren't using it.

The prevailing pattern is a static API key in an environment variable. It is convenient, it works on the first try, and it fails in every way that matters: copied between environments, so the credential no longer identifies where a request came from; rotated on a schedule nobody keeps; present in container images, CI logs and laptop dotfiles; and unattributable to a particular process on a particular host when abused. The infrastructure world worked through this for services and produced a standard. We think agents should inherit it, not rediscover it.

This post covers SPIFFE: what it specifies, how a workload obtains an identity without holding a secret, what attestation proves, and how trust domains federate across clusters and clouds. Then the part specific to agents. SPIFFE answers "which workload is this." It does not answer "on whose behalf, and for what purpose, is this workload acting." An agent is a non-deterministic workload acting for a user, and the second question decides whether a request should be allowed.

Two existing posts, Identity for AI Agents: A Primer and Agent Credentials vs. Human Credentials, work at the conceptual and IAM level. This post is the infrastructure layer underneath both. Token exchange and delegated authority are covered separately; here they appear only as the layer riding on top.

Picture a claims-processing agent at an insurer. It's invented for this post, but the shape is common: a pod in a Kubernetes cluster, reading from a policy-administration API, writing assessment notes to a document store, and occasionally calling a third-party medical-coding service in a different cloud account. Today it holds three static keys.

The design goal: no long-lived secret anywhere in the path. The workload's identity comes from what the platform can prove about it, not from something the workload was given at build time and now has to protect.

The Static Key Problem

The scale of static-credential sprawl is measured annually and the direction is not encouraging. GitGuardian's State of Secrets Sprawl 2026 reports 28.65 million hardcoded secrets added to public GitHub during 2025, a 34% year-on-year increase, with AI-service credentials the fastest-growing category. It also found 24,008 unique secrets in MCP-related configuration files, 2,117 of them valid, and that 64% of valid secrets first detected in 2022 were still not revoked in 2026. These are vendor-scanner figures rather than a census, but the revocation number is the one worth sitting with. Knowing a credential leaked is not the same as retiring it.

28.65M
hardcoded secrets added to public GitHub in 2025
34%
year-on-year increase
64%
secrets flagged in 2022 still unrevoked in 2026
Figure 1 — Static-credential sprawl, measured annually. Source

For the claims agent, the failures compound predictably. The policy-API key was issued once and shared with staging because staging needed realistic data. The document-store credential is in a Kubernetes Secret, which means it is in etcd, which means it is in etcd backups and in the CI system that applied the manifest. The medical-coding key belongs to a service account created by an engineer who has since left, and nobody is sure which of four workloads uses it. When the vendor reports anomalous volume on that key, the investigation cannot proceed past "one of ours."

Each follows from the same architectural choice: the credential is a bearer secret the workload possesses, so its security properties are the properties of possession. Anything that can read the value can be the workload. Workload identity inverts this. The credential becomes short-lived, issued to a specific attested process, and never stored durably.

What SPIFFE Specifies

SPIFFE (the Secure Production Identity Framework for Everyone) is a set of open specifications, with SPIRE as its reference implementation. Both graduated from the CNCF incubator in 2022, announced 20 September.

SPIFFE IDs. A workload identity is a URI: spiffe://trust-domain/path, the canonical documentation example being spiffe://acme.com/billing/payments. The trust domain is the trust root, typically one organisation, environment, or cluster, and everything after it is a path the operator assigns. The format is deliberately dull, which is why it composes. Istio derives service identities as spiffe://cluster.local/ns/<namespace>/sa/<service-account>, so a workload's mesh identity and its SPIFFE identity are the same string.

SVIDs. A SPIFFE Verifiable Identity Document proves the ID. An X.509-SVID is a short-lived certificate with the SPIFFE ID in the Subject Alternative Name URI field, plus its private key, usable directly for mutual TLS. A JWT-SVID is a signed JWT carrying the SPIFFE ID, for cases where a certificate cannot be presented end to end. The documentation is explicit that X.509 is preferred and JWT-SVIDs should be used only when there is no alternative, such as an L7 proxy in the path, because tokens are replayable in a way a private key held by the process is not.

The Workload API. This is where the secret disappears. A workload connects to a local gRPC endpoint, discovered through the SPIFFE_ENDPOINT_SOCKET environment variable whose value is a URI with a unix or tcp scheme, and calls FetchX509SVID, FetchJWTSVID, FetchX509Bundles or ValidateJWTSVID. The normative requirement that makes the model work is that the endpoint "MUST NOT require any direct authentication of its clients." Instead implementations should perform out-of-band authenticity checks (kernel introspection, orchestrator interrogation), and the chosen method "MUST NOT require the workload to actively participate." The workload need not know its own identity in advance, nor hold a token to ask for one. Clients keep the stream open and receive fully refreshed material on each update, which is how rotation becomes invisible.

Trust bundles. A bundle is the set of CA roots a workload should treat as trustworthy when validating peers. Bundles arrive over the Workload API alongside SVIDs, so a workload's view of who it can trust refreshes on the same channel and cadence as its own credential.

Policy APIClaims agentSPIRE ServerSPIRE AgentNodePolicy APIClaims agentSPIRE ServerSPIRE AgentNodeplatform evidencenode attestationagent SVIDWorkload API call, no credential presentedworkload attestation via kernel and k8s selectorsrequest SVID for matched entryX509-SVID, 1h TTLSVID plus trust bundle, rotated on streammTLS with SVIDresponse

SPIRE Agent --node attestation--> SPIRE Server | | claims agent --Workload API (no credential)--> SPIRE Agent | | workload attestation | +--request SVID for entry-------> | |<--X509-SVID (1h) ---------------+ claims agent <--SVID + trust bundle, rotated on open stream-- claims agent --mTLS with SVID--> Policy API No long-lived secret exists at any point in this path. -->

Figure 2 — Attestation to SVID issuance to resource call. The workload presents no credential to obtain a credential; the platform vouches for it.

SPIRE and Attestation

Attestation is the load-bearing part of all this, and where most of the engineering judgement lives. SPIRE splits it in two.

A SPIRE Server is the signing authority for one trust domain and holds the registration entries. A SPIRE Agent runs on each node, is attested to the server, and exposes the Workload API locally. Node attestation establishes that the agent runs on the host it claims: plugins exist for AWS EC2 Instance Identity Documents, Azure Managed Service Identities, GCP instance tokens, Kubernetes service account tokens, X.509 certificates and pre-shared join tokens. Workload attestation then establishes which process on that node is calling: the Unix attestor reads process attributes such as UID, GID and binary path; the Kubernetes attestor resolves the caller to a pod and therefore a namespace, service account and labels; the Docker attestor resolves container metadata.

A registration entry maps a SPIFFE ID to a set of selectors: the properties a workload must exhibit to receive that identity. The claims agent's entry might read:

shell
spire-server entry create \
  -parentID  spiffe://insurer.example/spire/agent/k8s_psat/prod-eu/node-7 \
  -spiffeID  spiffe://insurer.example/claims/assessor \
  -selector  k8s:ns:claims-prod \
  -selector  k8s:sa:claims-assessor \
  -selector  k8s:pod-label:app:claims-assessor \
  -federatesWith spiffe://coding-vendor.example

The security of this identity is exactly the security of those selectors. Namespace and service account are reasonable; a selector on a mutable pod annotation is not, because anything that can set the annotation can mint the identity. That is the honest limitation of workload attestation: it inherits the trust properties of the orchestrator. If an attacker can schedule a pod into claims-prod with that service account they get the identity, and no certificate rigour downstream repairs it. Workload identity moves the attack surface from "steal a string" to "compromise the platform's admission path," which is a large improvement and still not an elimination.

Lifetimes are short by default. SPIRE's server defaults are default_x509_svid_ttl of 1h, default_jwt_svid_ttl of 5m, and ca_ttl of 24h; the older combined default_svid_ttl field was deprecated in SPIRE v1.5.0 in favour of the two type-specific settings. A one-hour certificate that rotates on an open stream has a materially different risk profile from an API key valid since 2023, and it makes revocation a matter of removing a registration entry rather than chasing copies.

What attestation buys you: the credential is no longer a thing the agent has. It is a statement the platform makes, continuously, about a process it can observe. Deleting the entry ends the identity within one TTL.

Federation Across Trust Domains

The claims agent's third dependency, the medical-coding service, lives in another organisation's cloud. SPIFFE handles this through federation, which is a bundle-exchange problem rather than a new protocol.

Each SPIRE Server can expose a bundle endpoint serving its trust domain's bundle, and each server configures a federates_with block naming the peer's endpoint. Two profiles are defined. https_spiffe authenticates the endpoint with a SPIFFE identity over mutual TLS. It's stronger, but the requester must already hold the responder's bundle. https_web authenticates it with ordinary Web PKI using the CA certificates already in the OS trust store, removing the bootstrap problem at the cost of depending on public CAs.

Bootstrap is manual and deliberately so: operators exchange initial bundles with spire-server bundle show and spire-server bundle set. Updates are then fetched over the federation endpoint using the current bundle, so rotation is automatic and the manual step happens once. A workload registered with -federatesWith receives the foreign trust domain's bundle alongside its own SVID, and can validate an mTLS peer presenting spiffe://coding-vendor.example/... without either side sharing a secret or a CA.

Trust domain: coding-vendor.example (GCP)

Trust domain: insurer.example (AWS)

bundle endpoint https_web

bundle endpoint https_web

mTLS, peer validated
via federated bundle

SPIRE Server

Claims agent
spiffe://insurer.example/claims/assessor

SPIRE Server

Coding service
spiffe://coding-vendor.example/api

bundle endpoint ---- SPIRE Server | | claims agent ------------- mTLS, peer validated -------------> coding service spiffe://insurer.example/claims/assessor spiffe://coding-vendor.example/api Bootstrap once by hand (bundle show / bundle set); bundle updates flow over the endpoint thereafter. -->

Figure 3 — Trust-domain federation across two clouds. Neither side holds a credential belonging to the other; they hold each other's public trust material.

The Agent Gap

We think everything above is a solved problem worth adopting for agents. It's also insufficient, and being clear about why is the point of this post.

A SPIFFE identity answers a question about provenance: this connection comes from a process the platform attested as spiffe://insurer.example/claims/assessor. It says nothing about intent, authority, or the human in whose interest the process is currently acting. For a stateless microservice that difference doesn't arise. The service does one thing, so knowing which service it is tells you what it will do. An agent breaks the equivalence twice over: its behaviour is not determined by its code, so identity does not predict action, and a single instance serves many principals in sequence, so the same attested workload may legitimately act with wide authority in one request and none in the next.

Concretely, the claims agent's SVID is identical whether it's retrieving a claim on behalf of the handler assigned to it or on behalf of a contractor who is not. The mTLS handshake succeeds in both cases and should. The authorisation decision needs a second input the certificate cannot carry.

The pattern that actually works, in our view, separates the two cleanly. Use the SVID to authenticate the workload, then exchange it for a scoped, short-lived, audience-restricted access token that carries the delegated authority. The workload identity anchors the request in something the platform observed; the access token expresses what this request may do for this principal, narrowed per call. The mechanics of that exchange (delegation versus impersonation, the actor claim, downscoping) are covered in the token exchange post on this site. What matters here is that these are two layers, conflating them is the common mistake, and the failure modes differ: a compromised SVID leaks a workload's provenance, a compromised access token leaks a user's authority.

Attested workload identity
SPIFFE ID plus SVID

Answers: which workload is this?

Delegated authority
scoped short-lived access token

Answers: on whose behalf,
for what purpose?

Authorization decision at the resource

Allow or deny this action
for this principal

Figure 4 — Two layers, two questions. Workload identity is necessary and not sufficient.

Where the Standards Are

Three efforts are worth tracking here, and vendor material in this space routinely writes about drafts as though they were finished standards. That's worth correcting.

IETF WIMSE. The Workload Identity in Multi-System Environments working group is the chartered IETF effort here, addressing least-privilege access control for workloads across platforms and clouds. Its active documents include an architecture draft, a Workload Identifier draft defining a URI that identifies a workload within a trust domain, a Workload Credentials draft, a Workload Identity Practices survey of what platforms do today, and a Workload Proof Token (WPT) draft specifying how a workload proves possession of the key bound to a Workload Identity Token (WIT). WIMSE is close enough to SPIFFE that the SPIFFE Workload API already defines an optional WIT-SVID profile alongside its mandatory X.509 and JWT profiles.

draft-klrc-aiagent-auth. Version -00 was published 2 March 2026 by Pieter Kasselman (Defakto Security), Jeff Lombardo (AWS), Yaroslav Rosomakho (Zscaler) and Brian Campbell (Ping Identity). It's the first IETF draft to model AI agents explicitly as workloads needing identifiers and credentials, defining an agent as "a workload that iteratively interacts with a Large Language Model (LLM) and a set of Tools, Services and Resources," and proposing an Agent Identity Management System (AIMS) spanning eight dimensions: identifiers, credentials, credential provisioning, authentication, authorization, observability and remediation, policy, and compliance.

Its central normative statement is that an agent in the framework MUST be assigned exactly one WIMSE identifier, which MAY be a SPIFFE ID; credentials are X.509 certificates, WITs or JWT-SVIDs; authentication is mTLS at the transport layer or WPTs and HTTP Message Signatures at the application layer; and authorization is OAuth, with the delegating user in sub and the agent in client_id. For cross-domain cases it reaches for draft-ietf-oauth-identity-chaining (at -17, 19 July 2026, Standards Track), and for revocation the OpenID Shared Signals Framework. The draft has moved fast: -03 landed 6 July 2026, adding Nick Steele (OpenAI) and Aaron Parecki (Okta). It remains, though, an Informational individual submission with no formal standing in the IETF process, and it currently expires 7 January 2027. We'd treat it as the best available map of how the pieces fit, not as something to conform to.

Vendor implementations. Microsoft publishes microsoft/identity-spiffe, a Go sidecar (spiffe-proxy) combining Entra Agent Identity with SPIFFE/SPIRE SVIDs and enforcing four sequential checks before traffic reaches an application: mTLS caller verification, route-level RBAC, JWT validation, and Conditional Access-style risk signals, with any failed layer denying the request. It runs on Azure Container Apps with optional GCP and GitHub Actions federation and no shared secrets. It is also, in its own words, "a prototype... designed to show the pattern and make the implementation copyable, not to be run unchanged as a production platform." That's a fair read of where the industry is. The architecture is agreed. The productisation isn't finished.

If You Cannot Deploy SPIRE

Running SPIRE is real operational work: a highly available server, a per-node agent, a datastore, a registration-entry lifecycle, and a bootstrap story for every platform you run on. We think most teams running a handful of agents should skip it, not just defer it. If you have three agents and two environments, the SPIRE control plane will outweigh the problem it solves. The properties are still available incrementally, ordered below roughly by benefit per unit of effort.

  • Use the cloud's native workload identity federation. GKE Workload Identity Federation, EKS IRSA and Pod Identity via projected bound service-account tokens, and Entra Workload ID federated credentials all implement the same idea: the platform issues a short-lived OIDC token to an attested pod identity, exchanged for cloud credentials. The pod never holds a key and the audit record names the federated principal rather than a shared service account. This is SPIFFE's model with the cloud provider as attestor, available today with no new infrastructure.
  • Give every agent, in every environment, its own identity. One credential per agent per environment, never shared. This is the single change that makes attribution possible and revocation surgical, and it requires no new technology, only the discipline to stop reusing the key that already works.
  • Shorten every lifetime you control. Move from static keys to OAuth clients with short access-token lifetimes and refresh, at the shortest expiry the target system tolerates. An hour is a different security posture from a year even with no other change.
  • Bind credentials to the caller where the provider allows it. mTLS- or DPoP-bound tokens, IP and VPC-endpoint restrictions, and audience restrictions all reduce a stolen token's value.
  • Sequence the migration deliberately. Inventory every credential an agent holds and which workload uses it; issue a distinct per-agent-per-environment credential and cut over one at a time; track last-use so you can prove the old key is dead; then revoke it rather than leaving it valid "in case." The GitGuardian revocation figure suggests most organisations' real problem is not detection but the absence of a repeatable path to retirement, and the final step is always the one that slips.

Conclusion

The static key in an environment variable is the weakest part of most agent deployments, and it is weak for a structural reason: it makes identity a function of possession. SPIFFE replaces possession with attestation: a SPIFFE ID naming the workload, an SVID that expires in an hour, a Workload API that hands it over without asking the workload to authenticate, and federation that lets two organisations validate each other without either holding the other's secret. SPIRE makes this concrete; the cloud providers' workload identity federation offers most of the same properties without new infrastructure.

What none of it does is answer the question an agent actually raises. Provenance is not authority. Our read is that the architecture which actually holds up pairs a cryptographic workload identity underneath with a scoped, short-lived, audience-restricted delegated token on top, and requires the resource to check both. WIMSE and draft-klrc-aiagent-auth describe exactly this composition; the layering is agreed and the details are still moving.

And we'd still say: get the workload-identity discipline right before reaching for SPIRE specifically. The federation most teams actually need already ships from their cloud provider.

Attestation replaces possession. The question stops being "who has the key" and becomes "what can the platform prove about this process, and what has its user actually authorised it to do." Those are two questions, and a design that answers only the first has solved the easier half.

Sources