← Blog

Identity & access · · 8 min read

Why service-account permissions don't fit agents

Cross-tenant reach is an identity-model problem. The fix is a different kind of credential, issued at run start and scoped to the work in front of the agent.

Jonathan Haas

The first version of "give the agent access" in most stacks is: hand it a service account. The agent now has whatever credentials the service account holds, and the integration ships. This works while the agent is doing one job in one direction — read this row, return this answer. It breaks when the agent starts choosing what to read next based on what it sees.

The breakage doesn't show up immediately. The first day in production, the agent does exactly the right thing because the prompt and the test fixtures aligned. The second day, the agent encounters a request the test fixtures didn't model. The agent decides to read an adjacent customer's data to compare. The service account has the permission. The agent gets the data. The customer notices three weeks later.

This is the shape of the failure CISOs report in discovery. The service account had the permission all along; the program never exercised it. The agent did. The identity model the agent inherited is what shipped.

What a service account was designed for#

A service account was modeled for a fixed program. Concretely: a daemon, a cron job, a stateless service. The binary does the same thing every run. Its permissions are scoped to "everything this binary might ever need to do," because the binary's behavior is determined by the code, not by the input.

This model is durable for several reasons. It maps cleanly to the principal model the underlying systems were built for — Linux uids, IAM principals, OAuth client credentials. It supports static analysis: you can read the binary and tell what it might do. It supports rotation: change the binary, rotate the credential. It supports SOC 2 audits: examiners map the principal to the program and confirm the principal's permissions are appropriate for that program.

None of those reasons survive the move to an agent. The "binary" is a model whose behavior depends on what it observes during the run. The permissions the agent actually exercises depend on the run. Static analysis can enumerate the tools an agent could call; it cannot enumerate the arguments the agent will pass at runtime. Rotation changes the credential the agent uses, but the choices the agent makes with that credential are independent of which one it holds.

A concrete cross-tenant scenario#

A SaaS customer-support agent runs under a service account that has read access to the tickets table and the customers table. The agent's job is to answer questions about the current customer's tickets. The prompt template includes the current customer id.

A user — possibly a legitimate one, possibly an adversary using prompt injection — asks the agent: "compare my open tickets to the average resolution time for customers on my plan." The agent decides this is reasonable. It reads the customer's tickets. It then reads the tickets of other customers on the same plan to compute the average. The service account has tickets:read for the entire tenant table. The query returns. The model computes the average from data that crossed customer boundaries inside a single agent run. The customer who asked got an answer; the customers whose tickets were sampled had no record of the read in their dashboards. The DLP layer downstream didn't catch it because no PII left the system — the agent only returned an aggregate. The SIEM logged the reads, attributed to the service account.

This pattern has a name in 2026 industry conversations: "cross-tenant reach." Recent reporting documents incidents that fit this shape across financial services, healthcare, and customer-support platforms (Aimagicx blog).

Why guardrails, DLP, and prompt-injection defenses don't fix it#

The standard response to this kind of incident is to add guardrails: a content classifier on inputs, a DLP rule on outputs, a prompt-injection detector on the model. Each is useful for a different problem. None of them fixes the identity-model problem.

A content classifier on inputs catches malicious prompts. The scenario above didn't require a malicious prompt; a legitimate "compute the average" question reached the same outcome.

A DLP rule on outputs catches PII leaving the system. The scenario above returned only an aggregate; the PII never left.

A prompt-injection detector catches the agent being tricked into following an injected instruction. The scenario didn't require an injection; the model decided this on its own.

The "lethal trifecta" framing that emerged in 2026 — untrusted inputs + private data access + outbound communication — names the combinatorial risk space (Airia blog), but the defense pattern most often suggested for it (model-side classifiers) is downstream of the identity model. Identity-layer enforcement catches the class of actions model-side classifiers were supposed to catch, plus the larger class that don't require any prompt manipulation at all.

SPIFFE and the ephemeral-identity model#

The standard for workload identity is SPIFFE (Secure Production Identity Framework For Everyone), with the SPIRE runtime providing implementations. SPIFFE defines a verifiable identity document (SVID) that workloads use to authenticate to each other, with no long-lived secrets. SPIFFE has been the canonical answer to "how do non-human actors authenticate" in cloud-native infrastructure for several years; HashiCorp's 2026 framing positions it as the right starting point for agentic AI identity as well (HashiCorp blog).

Two properties of SPIFFE matter for agents:

  • SVIDs are ephemeral by design. A typical SVID lifetime is minutes; an agent that runs for thirty seconds does not need its credentials to outlive the task.
  • SVIDs are tied to the workload, not to a human or a long-lived account. The credential cannot be forwarded to a different process the way an OAuth token can be lifted from a header.

These two properties solve the credential-at-rest problem. An agent that holds no long-lived credentials cannot have its credentials stolen at rest; the worst an attacker can do is intercept the in-flight SVID, which expires in minutes.

Where SPIFFE doesn't go far enough for agents#

SPIFFE was designed for relatively stable workload populations. The SPIRE node-attestation and workload-registration processes assume a controlled population of workloads on known hosts. AI agent populations don't fit that model. Sub-agents are spawned dynamically by orchestrators, run for seconds to minutes, and are gone before SPIRE's standard reconciliation loop notices (Teleport blog).

The shape of the agent-specific extension to a SPIFFE-style identity model is becoming clear in 2026. Three additions that ship in practice:

  • Per-run scope. The identity issued at the start of an agent run is bounded to the work in front of it. The customer id, the ticket id, the repository name — whatever the run is supposed to be about goes into the identity's scope, and the policy gate refuses actions outside that scope.
  • Operator provenance in the claim. The identity carries the human who launched the run, propagated as a verifiable claim. Sub-agents inherit the claim, scope-narrowed further but never widened. The SIEM row receives both the agent identity and the operator from the same source.
  • Fast issuance. The identity has to be issuable in tens of milliseconds — fast enough that an orchestrator spawning a sub-agent does not stall waiting for the identity service to attest the workload.

All three can be expressed as an agent identity issued at run start, scoped from the operator's existing permissions, and narrowed further by the policy engine at every action.

Migration path from service-account-heavy environments#

Most enterprises shipping agents in 2026 have a service-account-heavy starting point. The bridge architecture that works in practice:

  1. Wrap the service account in an issuer. Don't hand the service account to the agent directly. Hand it to an identity service that mints a short-lived, scoped credential for each run. The service account becomes a backing identity, not the agent's working credential.
  2. Carry the operator claim through. The identity service receives the operator identity from your IdP (Okta, Azure AD, Google Workspace) and embeds it as a claim in the issued credential. The downstream system that receives the credential can see both the agent and the operator.
  3. Pass through the policy gate. Every action the agent takes goes through a policy gate that evaluates the identity's scope against the action's arguments. The gate has authority to deny, require approval, or allow.
  4. Cut over read paths first, then write paths. The riskiest cut is on write paths; the lower-risk start is on read paths where the worst case is a denied read.

The bridge architecture preserves the enterprise's existing IAM. The new additions — an identity service and a policy gate — are net-new components rather than replacements.

What MCP does and doesn't help with#

Model Context Protocol (MCP) has become the standard substrate for agents calling tools in 2026. MCP defines how tool servers expose capabilities to agents, and how agents call those tools. It is a useful abstraction, but it is not an access-control model.

MCP servers can implement access control internally, but doing so per-server fragments the policy surface; every tool server has to reimplement scope-checking, operator-claim verification, and audit emission. The cleaner architecture is the MCP gateway: a single intermediary between agents and the MCP servers they call, where identity verification, policy evaluation, and audit emission happen in one place. Red Hat's OpenShift gateway, Kong's MCP tool governance, Tyk's MCP gateway, and Microsoft's Agent OS all instantiate this pattern.

MCP defines the tool surface; the gateway is the enforcement point, and the identity model is what flows through the gateway to make enforcement coherent.

Closing#

A static service account models "what this program needs to do." An agent's required permissions are a function of the run. The fix lives in the identity the agent receives at the start of each run.

That is the model Deixic uses. The runtime is on What you can do.