<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>AI Agents on Matt Goodrich</title><link>https://mattgoodrich.com/tags/ai-agents/</link><description>Recent content in AI Agents on Matt Goodrich</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Wed, 27 May 2026 12:00:00 -0700</lastBuildDate><atom:link href="https://mattgoodrich.com/tags/ai-agents/index.xml" rel="self" type="application/rss+xml"/><item><title>Agents Need Capabilities, Not Roles</title><link>https://mattgoodrich.com/posts/agents-need-capabilities-not-roles/</link><pubDate>Wed, 27 May 2026 12:00:00 -0700</pubDate><guid>https://mattgoodrich.com/posts/agents-need-capabilities-not-roles/</guid><description>&lt;img src="https://mattgoodrich.com/posts/agents-need-capabilities-not-roles/header.png" alt="Featured image of post Agents Need Capabilities, Not Roles" />&lt;p>&lt;strong>An AI agent is not a user, and permissioning one like a user is the most expensive shortcut in the AI rollout.&lt;/strong>&lt;/p>
&lt;p>A user is a person with judgment, a slow reaction time, and a strong incentive not to do anything that gets them fired. The permission model you grant a user assumes all three. A user with database write access does not, in practice, drop tables, because their hand stalls at the keyboard before the command runs.&lt;/p>
&lt;p>An agent has none of those properties. It executes the action it was prompted into in milliseconds. It does not stall. It does not weigh the social consequence. It carries the user&amp;rsquo;s identity, and therefore the user&amp;rsquo;s access, but applies none of the user&amp;rsquo;s judgment. The shortcut of just inheriting the invoking user&amp;rsquo;s auth at agent runtime is the version of this mistake most companies are making right now, and the bill for it will come due in a postmortem nobody wants to write.&lt;/p>
&lt;p>I argued in &lt;a class="link" href="https://mattgoodrich.com/posts/ai-governance-existing-controls-identity-guardrails/" >AI Governance, Calibrated&lt;/a> that most of the controls we need already exist and the gap is the identities granted to agents. This post goes one layer deeper. The identity model itself has to change. The right model has been sitting in security infrastructure for fifty years. Most teams just have to apply it.&lt;/p>
&lt;h2 id="security-has-known-this-since-1973">Security Has Known This Since 1973
&lt;/h2>&lt;p>Unix shipped with &lt;code>rwx&lt;/code> in the early seventies, and POSIX formalized it in 1988. Three bits per principal, granting one specific action each: read, write, execute. It is the original implementation of action-based authorization. The system did not ask whether you were &lt;em>senior&lt;/em> or &lt;em>trusted&lt;/em>. It asked whether the action you were trying to perform was on your list. The granularity was the action, not the role.&lt;/p>
&lt;p>Capability-based security predates even that. &lt;a class="link" href="https://dl.acm.org/doi/10.1145/365230.365252" target="_blank" rel="noopener"
>Dennis and Van Horn published the idea in 1966&lt;/a>: instead of asking the system whether a subject is allowed to take an action against an object, hand the subject an unforgeable token (a &lt;em>capability&lt;/em>) that authorizes the specific action against the specific object. The model held for decades, mostly in academic and high-assurance contexts, because issuing and revoking capabilities at scale was inconvenient.&lt;/p>
&lt;p>The cloud era brought it back. &lt;a class="link" href="https://docs.aws.amazon.com/IAM/UserGuide/reference_policies_actions-resources-contextkeys.html" target="_blank" rel="noopener"
>AWS IAM actions&lt;/a> are exactly this idea, named in modern form. &lt;code>s3:GetObject&lt;/code> is read. &lt;code>s3:PutObject&lt;/code> is write. &lt;code>iam:DeleteRole&lt;/code> is destruction. The policy grants the action against the resource, and the identity is just whoever happens to carry the policy. OAuth scopes are the same thing at the application layer. &lt;code>read:user&lt;/code>, &lt;code>write:repo&lt;/code>, &lt;code>admin:org&lt;/code>: each scope is a capability the third-party app received from the user. Modern security architects have been writing these policies for fifteen years.&lt;/p>
&lt;p>What none of that was designed for was an identity that acts thousands of times per minute at machine speed and was never told no by an HR conversation. That is what an AI agent is. The heritage is right; the application has to catch up.&lt;/p>
&lt;h2 id="six-action-classes-by-blast-radius">Six Action Classes by Blast Radius
&lt;/h2>&lt;p>The granularity of &amp;ldquo;every AWS IAM action&amp;rdquo; works for human-written IAM policies, but it is too fine for governing an agent&amp;rsquo;s overall behavior. An agent that can call &lt;code>s3:GetObject&lt;/code> against ten buckets but not &lt;code>s3:DeleteObject&lt;/code> against any is doing something coherent at the policy level and incoherent at the program level. The security-relevant question for an agent is not &amp;ldquo;which API calls is it allowed to make,&amp;rdquo; it is &amp;ldquo;what class of damage can it do, and how reversible is that damage.&amp;rdquo;&lt;/p>
&lt;p>Six classes, grouped by what fails if it is wrong, and ordered by escalating blast radius.&lt;/p>
&lt;p>&lt;strong>Observation.&lt;/strong> Reads, queries, searches, inspections. The agent looks at something but does not change it. Reversible by definition, because the system state does not move. Default-grant for any new agent within its data classification boundary.&lt;/p>
&lt;p>&lt;strong>Drafting.&lt;/strong> Recommendations, summaries, proposed changes that exit the system as text to a human or another agent for review. The output is consumed downstream but no state in the system has been modified. Reversible because the &lt;em>agent&lt;/em> did not act, the downstream consumer did.&lt;/p>
&lt;p>&lt;strong>Modification.&lt;/strong> Writes, updates, configuration changes inside the system. Reversible with effort: a git revert, a configuration rollback, a database restore. Default-deny; granted per workflow with logging and a defined recovery path.&lt;/p>
&lt;p>&lt;strong>Sanction.&lt;/strong> Approvals, denials, escalations. The agent makes a downstream-binding decision on someone else&amp;rsquo;s behalf: approves a refund, denies a ticket, escalates a deal-terms negotiation. Reversibility depends on what the downstream consumer does. Default-deny; granted only with a maker-checker pattern in place.&lt;/p>
&lt;p>&lt;strong>Execution.&lt;/strong> Triggering side effects beyond the current system. Running a deployment, kicking off a workflow, initiating a transaction, posting to a customer-facing channel. The agent has reached out of the sandbox. Default-deny; granted only with a documented kill switch and a per-action approval policy.&lt;/p>
&lt;p>&lt;strong>Destruction.&lt;/strong> Deletes, revokes, permanent terminations. Irreversible by definition. Default-deny, always, with no exceptions automated by the agent itself. Every destruction action escalates to a named human, regardless of the agent&amp;rsquo;s confidence in itself.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Class&lt;/th>
&lt;th>Example actions&lt;/th>
&lt;th>Reversibility&lt;/th>
&lt;th>Default policy and grant requirement&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>Observation&lt;/strong>&lt;/td>
&lt;td>Reads, queries, searches, inspections&lt;/td>
&lt;td>Reversible by definition&lt;/td>
&lt;td>Default-grant within data classification boundary&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Drafting&lt;/strong>&lt;/td>
&lt;td>Recommendations, summaries, proposed changes that exit as text for review&lt;/td>
&lt;td>Reversible — downstream consumer acts, not the agent&lt;/td>
&lt;td>Earned after Observation period; review and acceptance rate tracked&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Modification&lt;/strong>&lt;/td>
&lt;td>Writes, updates, configuration changes inside the system&lt;/td>
&lt;td>Reversible with effort (revert, rollback, restore)&lt;/td>
&lt;td>Default-deny; granted per workflow with logging and a defined recovery path&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Sanction&lt;/strong>&lt;/td>
&lt;td>Approvals, denials, escalations on someone else&amp;rsquo;s behalf&lt;/td>
&lt;td>Depends on what the downstream consumer does&lt;/td>
&lt;td>Default-deny; granted only with a maker-checker pattern in place&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Execution&lt;/strong>&lt;/td>
&lt;td>Deployments, transactions, customer-facing posts&lt;/td>
&lt;td>Often irreversible&lt;/td>
&lt;td>Default-deny; granted only with a documented kill switch and per-action approval policy&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Destruction&lt;/strong>&lt;/td>
&lt;td>Deletes, revokes, permanent terminations&lt;/td>
&lt;td>Irreversible by definition&lt;/td>
&lt;td>Default-deny always; every action escalates to a named human&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Read this as a security-architecture reference, not as a coined dichotomy. The class names are what I find useful; the underlying axis is what matters. What does the agent do? What fails if it is wrong? How hard is it to put back? Every authorization decision an agent&amp;rsquo;s policy makes is one of those three questions answered.&lt;/p>
&lt;h2 id="promotion-through-classes-is-the-trust-ladder">Promotion Through Classes Is the Trust Ladder
&lt;/h2>&lt;p>A new agent does not get all six classes on day one. It gets &lt;em>Observation&lt;/em> and earns the rest, one class at a time, against measured evidence.&lt;/p>
&lt;p>The promotion path runs from least to most consequential. An agent in &lt;em>Observation&lt;/em> runs read-only against the systems in its scope, with full logging. After a defined observation period (measured in incidents avoided and false positives caught, not calendar days), the agent earns &lt;em>Drafting&lt;/em>. Its output goes to humans for review, the review is logged, and the percentage of accepted drafts is tracked. After a second window of measured eval, with the catch rate of its reviewer holding above threshold, &lt;em>Modification&lt;/em> unlocks with a per-write approval gate. &lt;em>Sanction&lt;/em> requires the maker-checker pattern to be wired in and measured for false-positive rate on the checker. &lt;em>Execution&lt;/em> requires a documented kill switch tested in a non-production drill. &lt;em>Destruction&lt;/em> may never unlock at all for some agents, and that is the correct answer.&lt;/p>
&lt;p>&lt;img src="https://mattgoodrich.com/posts/agents-need-capabilities-not-roles/diagram-trust-ladder.png"
width="595"
height="2541"
srcset="https://mattgoodrich.com/posts/agents-need-capabilities-not-roles/diagram-trust-ladder_hu3577549802464180522.png 480w, https://mattgoodrich.com/posts/agents-need-capabilities-not-roles/diagram-trust-ladder_hu9597434463706962401.png 1024w"
loading="lazy"
alt="Trust ladder: six action classes connected by measurement gates, with demotion automatic on threshold breach"
class="gallery-image"
data-flex-grow="23"
data-flex-basis="56px"
>&lt;/p>
&lt;p>The mistake every team makes here is allowing time to substitute for evidence. Six months on the job is not promotion criteria. A measured drift indicator within tolerance, an incident rate at or below baseline, a reviewer catch rate above a numerical threshold: those are promotion criteria. Demotion is automatic on threshold breach.&lt;/p>
&lt;p>The shape of this ladder is not new either. &lt;a class="link" href="https://csrc.nist.gov/pubs/sp/800/37/r2/final" target="_blank" rel="noopener"
>NIST SP 800-37&amp;rsquo;s Risk Management Framework&lt;/a> already structures the &lt;em>authorize-to-operate&lt;/em> progression as a sequence of gates evidenced by measurement. &lt;a class="link" href="https://www.fedramp.gov/" target="_blank" rel="noopener"
>FedRAMP&amp;rsquo;s authorization levels&lt;/a> follow the same pattern. What changes for agents is the cadence. Human service accounts get promoted over months. Agents have to be re-evaluated continuously, because the model underneath them changes, and so does the input distribution they operate on.&lt;/p>
&lt;h2 id="mapping-to-the-isms-you-already-run">Mapping to the ISMS You Already Run
&lt;/h2>&lt;p>Here is the part that most agent-governance content skips, and most security leaders will care about most. The framework above does not require a new control set. It maps onto the standards already in your ISMS.&lt;/p>
&lt;p>The action-class taxonomy maps to &lt;strong>&lt;a class="link" href="https://csrc.nist.gov/pubs/sp/800/53/r5/upd1/final" target="_blank" rel="noopener"
>NIST SP 800-53 AC family&lt;/a>&lt;/strong> directly. &lt;em>Observation&lt;/em> is AC-3 access enforcement against the read role. &lt;em>Modification&lt;/em> and &lt;em>Destruction&lt;/em> fall under AC-6 Least Privilege and AC-6(9) Auditing of Privileged Use. &lt;em>Execution&lt;/em> triggers AC-17 Remote Access concerns. The agent&amp;rsquo;s per-class authorization policy is just an AC-2 Account Management exercise with the agent as a new class of account.&lt;/p>
&lt;p>The promotion ladder maps to &lt;strong>&lt;a class="link" href="https://csrc.nist.gov/pubs/sp/800/37/r2/final" target="_blank" rel="noopener"
>NIST SP 800-37 Risk Management Framework&lt;/a>&lt;/strong>. The agent goes through Categorize, Select, Implement, Assess, Authorize, Monitor exactly the way a system component does. Each class-promotion is an authorize-to-operate decision with evidence packaged for the AO.&lt;/p>
&lt;p>The evidence-packet discipline maps to &lt;strong>&lt;a class="link" href="https://csrc.nist.gov/pubs/sp/800/218/a/final" target="_blank" rel="noopener"
>NIST SP 800-218A&lt;/a>&lt;/strong> (Secure Software Development Framework for AI Systems). The packet is what the SSDF asks for: artifact-level proof of testing, adversarial probing, and human review.&lt;/p>
&lt;p>The agent-as-a-managed-system view maps to &lt;strong>&lt;a class="link" href="https://www.iso.org/standard/42001" target="_blank" rel="noopener"
>ISO/IEC 42001:2023&lt;/a> Annex A&lt;/strong>. A.6 covers the AI lifecycle (design through operation). A.9 covers the responsible use of the system. A.10 covers supplier and customer relationships when the agent acts on someone&amp;rsquo;s behalf.&lt;/p>
&lt;p>The threat surface maps to &lt;strong>&lt;a class="link" href="https://genai.owasp.org/resource/agentic-ai-threats-and-mitigations/" target="_blank" rel="noopener"
>OWASP Agentic AI Threats v1.1&lt;/a>&lt;/strong>. Privilege Compromise (action-class scoping is the mitigation), Tool Misuse (the tool surface is enumerated and bounded), Resource Overload (cost cap and rate limit), Memory Poisoning (the &lt;em>Modification&lt;/em> class includes memory writes and requires the same governance as state writes).&lt;/p>
&lt;p>None of this is new control work. It is mapping the agent into the existing controls. The ISMS already has the management-system spine: risk assessment, policy, internal audit, management review, continual improvement. The agent extends the scope; it does not start a parallel program.&lt;/p>
&lt;h2 id="what-holds-the-taxonomy-up-in-production">What Holds the Taxonomy Up in Production
&lt;/h2>&lt;p>Three pieces of operational discipline make the action-class taxonomy work in production. None of them are AI-specific; all of them are sharper now because the agent acts faster than the human reviewer.&lt;/p>
&lt;p>&lt;strong>The evidence packet.&lt;/strong> Every consequential output the agent produces ships with a packet: the spec it was given, the tests run against the output, the adversarial probes (fuzzing, prompt-injection, edge cases), the static analysis or symbolic exploration results where they apply, the change history, and the signature of the reviewer (human or agent) that signed off. The packet is the audit trail a future investigator will look at, and it is the eval set the next month&amp;rsquo;s drift detection will run against. It is also what an auditor wants instead of &amp;ldquo;the agent did this and we trust it.&amp;rdquo; &lt;a class="link" href="https://slsa.dev/" target="_blank" rel="noopener"
>SLSA&lt;/a> gave us this discipline for build provenance. Agents need it for action provenance.&lt;/p>
&lt;p>&lt;strong>The maker-checker pattern.&lt;/strong> A primary agent makes the proposal. A second system, whether a review agent with a different objective function, a hard-coded check, or a human at the consequential gates, examines whether the proposal matches the spec, fits within policy, and avoids the irreversible class without explicit authorization. The pattern is older than computing; banking has run it for centuries. The novel part is making the checker an agent rather than a person at the volumes agents now produce. OpenAI&amp;rsquo;s internal alignment team &lt;a class="link" href="https://alignment.openai.com/scaling-code-verification/" target="_blank" rel="noopener"
>published a number worth remembering&lt;/a>: their Codex-based PR reviewer leaves comments that the author addresses with a code change 52.7% of the time. That is the right kind of metric. Calibrate your eval coverage against the checker&amp;rsquo;s measured catch rate, not against the absence of incidents.&lt;/p>
&lt;p>&lt;strong>Escalation triggers.&lt;/strong> Some conditions always escalate, regardless of agent state: any action in the &lt;em>Destruction&lt;/em> class, any &lt;em>Execution&lt;/em> against production. Some escalate based on agent state: cost over threshold, the agent&amp;rsquo;s own confidence below cutoff, telemetry drift against baseline. &lt;a class="link" href="https://nvlpubs.nist.gov/nistpubs/ai/NIST.AI.600-1.pdf" target="_blank" rel="noopener"
>NIST AI 600-1&lt;/a> MG-2.4-001 and MG-2.4-002 already require auto-suspension on resource consumption breaches; OWASP Agentic adds confidence-based and drift-based escalation. The work is not deciding &lt;em>whether&lt;/em> to escalate. The standards already say. The work is choosing the thresholds and the path.&lt;/p>
&lt;h2 id="where-this-fails">Where This Fails
&lt;/h2>&lt;p>The action-class taxonomy carries the load for everything that maps cleanly to permission, but three concerns do not, and the post would oversell if it skipped them.&lt;/p>
&lt;p>&lt;strong>Memory poisoning has no Unix analog.&lt;/strong> An agent&amp;rsquo;s memory layer is not a file with rwx bits on it. When upstream input contains instructions that change the agent&amp;rsquo;s future behavior (a document the agent retrieved, a tool response, a teammate-agent message), no per-action policy catches it. The mitigation is OWASP&amp;rsquo;s: session isolation, source attribution for memory updates, version control on the memory layer, snapshots for forensic rollback. None of those look like POSIX. This is genuinely new security work.&lt;/p>
&lt;p>&lt;strong>Prompt injection lives at the tool boundary.&lt;/strong> A tool that returns text the agent will read can contain instructions the agent will follow. Action-class authorization does not stop the agent from reading the malicious text and then performing an authorized action it was tricked into performing. The mitigation is at the tool layer (sanitize inputs, contain tool outputs, never let an agent loop indefinitely on uncontrolled inputs), and it is partially solvable, but the solution is not the action taxonomy.&lt;/p>
&lt;p>&lt;strong>Cost runaway is fast.&lt;/strong> A human service account that decides to retry an expensive API call eats one cycle of cost and gets noticed at scale. An agent that decides to retry can burn the monthly cloud budget in an hour. The kill switch has to fire on cost the same way it fires on irreversibility, and the cost telemetry has to be in the agent&amp;rsquo;s loop, not in a dashboard a human reviews next week.&lt;/p>
&lt;p>The action-class taxonomy is the right model for what an agent &lt;em>does&lt;/em>. It is not the model for what gets &lt;em>done to&lt;/em> the agent, or for what the agent does to itself. Those need their own controls, and they need to be wired in alongside the per-class policy, not instead of it.&lt;/p>
&lt;h2 id="what-posix-knew-applied-forward">What POSIX Knew, Applied Forward
&lt;/h2>&lt;p>The security discipline that governs an AI agent has been written down for fifty years. POSIX scoped the action to the file. Capability-based security gave the action a token. AWS IAM actions and OAuth scopes generalized the model. The principle has been the same since 1973: the permission belongs to the action, not the identity.&lt;/p>
&lt;p>What is new in 2026 is that the identity now acts faster than the change-management process can move. The mitigation is not a new framework. It is a tighter application of the framework already in your ISMS, with the agent enrolled as the new class of privileged service account it actually is.&lt;/p>
&lt;p>Permission an agent the way you would permission any service account that runs as root in production: by action, by blast radius, by the evidence it can produce. The architecture is half a century old. The work is teaching your existing program to apply it to a new kind of caller.&lt;/p></description></item><item><title>Agent Identities Are Service Accounts That Improvise</title><link>https://mattgoodrich.com/posts/service-accounts-that-improvise/</link><pubDate>Tue, 26 May 2026 12:00:00 -0700</pubDate><guid>https://mattgoodrich.com/posts/service-accounts-that-improvise/</guid><description>&lt;img src="https://mattgoodrich.com/posts/service-accounts-that-improvise/header.png" alt="Featured image of post Agent Identities Are Service Accounts That Improvise" />&lt;p>&lt;strong>An AI agent&amp;rsquo;s identity is a non-human identity, and ninety percent of what governs it is decades-old hygiene. The other ten percent is where most agent rollouts fail.&lt;/strong>&lt;/p>
&lt;p>I came into this post not knowing whether to call agent identities a genuinely new class of non-human identity or just service accounts that improvise. After looking at what is published and what is failing in production, the honest answer is both. The base disciplines that govern any non-human identity (short-lived credentials, scoped per-action permissions, identity separated from the invoking user, audit on every call) are the disciplines that govern an agent. They have been the right answer for fifteen years. Most companies still have not implemented them, and the agent rollout is what is finally forcing the bill due.&lt;/p>
&lt;p>What is actually new is narrower than the AI conversation usually allows, and more dangerous than the NHI conversation usually admits. Three new failure modes have no service-account analog. Prompt injection turns adversarial text into control flow. Model versioning rewrites what the agent does without rewriting who it is. Multi-hop delegation across tools confuses the principal in ways OAuth was not designed to handle. Those three are the genuinely new ground.&lt;/p>
&lt;p>This post examines what is the same, what is different, and what that means for identity practice. The follow-on post argues the authorization model that falls out of it.&lt;/p>
&lt;h2 id="whats-already-decades-old-hygiene">What&amp;rsquo;s Already Decades-Old Hygiene
&lt;/h2>&lt;p>Most of what makes an agent identity work is what makes any non-human identity work, and it has been correct since the 2010s.&lt;/p>
&lt;p>Service accounts should have their own identity, separate from any human invoker. They should authenticate with short-lived credentials minted at execution, not long-lived API keys checked into config files. They should be scoped to the specific actions their workload requires, not granted broad role membership. Every action they take should land in an audit log with the service identity attributed. The service account should have a named human owner, a documented purpose, and a lifecycle that retires it when the workload retires. None of this is novel. &lt;a class="link" href="https://spiffe.io/" target="_blank" rel="noopener"
>SPIFFE&lt;/a> has issued workload identities to Kubernetes pods since 2018. &lt;a class="link" href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html" target="_blank" rel="noopener"
>AWS IAM roles&lt;/a> have minted short-lived credentials for EC2 instances for longer than that. The discipline is fifteen years old.&lt;/p>
&lt;p>What is fresh is the volume. The Cloud Security Alliance&amp;rsquo;s &lt;a class="link" href="https://cloudsecurityalliance.org/artifacts/state-of-nhi-and-ai-security-survey-report" target="_blank" rel="noopener"
>&lt;em>State of NHI and AI Security&lt;/em>&lt;/a> survey found that most organizations are still in &lt;em>discovery&lt;/em> for basic NHI inventory. They do not know how many service accounts they have, who owns them, or what they are authorized to do. The agent rollout exposes the same gap at a faster cadence, because every new agent is a new identity, every new tool integration is a new credential boundary, and the count grows weekly. &lt;a class="link" href="https://blog.gitguardian.com/the-state-of-secrets-sprawl-2026/" target="_blank" rel="noopener"
>GitGuardian&amp;rsquo;s 2025 numbers&lt;/a> put a finer point on it: 28.6 million secrets leaked to public GitHub in 2025, up 34% year over year, with 1.2 million tied specifically to AI services and up 81% year over year. AI is making the existing NHI hygiene gap explode, not creating a fundamentally new gap.&lt;/p>
&lt;p>If your security program does not have an NHI inventory today, the right first move is not &amp;ldquo;add agent identity tooling.&amp;rdquo; It is finishing the NHI discipline that should have been finished by 2022. The agent rollout magnifies whatever your NHI posture already is. It does not improve it on its own.&lt;/p>
&lt;h2 id="whats-actually-new">What&amp;rsquo;s Actually New
&lt;/h2>&lt;p>Three things have no service-account analog. They are the entire reason &amp;ldquo;just treat the agent like a service account&amp;rdquo; is incomplete.&lt;/p>
&lt;p>&lt;strong>Prompt injection turns adversarial text into control flow.&lt;/strong> A service account is told to do exactly one thing by the code that invokes it. An agent reads inputs and decides what to do based on them. If those inputs include text that &lt;em>looks like&lt;/em> instructions, the agent will sometimes follow them. The OWASP LLM Top 10 names this &lt;a class="link" href="https://genai.owasp.org/llmrisk/llm01-prompt-injection/" target="_blank" rel="noopener"
>LLM01:2025 Prompt Injection&lt;/a>; the &lt;a class="link" href="https://genai.owasp.org/resource/owasp-top-10-for-agentic-applications-for-2026/" target="_blank" rel="noopener"
>Agentic AI Top 10&lt;/a> names the operational version ASI03 Identity and Privilege Abuse. The attack pattern is now documented in the wild. &lt;a class="link" href="https://www.aim.security/lp/aim-labs-echoleak-m365" target="_blank" rel="noopener"
>Aim Security&amp;rsquo;s June 2025 disclosure&lt;/a> of CVE-2025-32711 (&amp;ldquo;EchoLeak&amp;rdquo;) showed zero-click prompt injection against Microsoft 365 Copilot, exfiltrating confidential data without user interaction. Invariant Labs in May 2025 demonstrated the &amp;ldquo;&lt;a class="link" href="https://invariantlabs.ai/blog/mcp-github-vulnerability" target="_blank" rel="noopener"
>GitHub MCP data heist&lt;/a>&amp;rdquo;: a malicious public-repo issue caused Claude with the GitHub MCP installed to copy private repository contents into a public pull request. No service account has ever been tricked into doing this by text.&lt;/p>
&lt;p>&lt;strong>Model version is an identity property.&lt;/strong> The agent&amp;rsquo;s behavior depends on the model it is running under. A permission grant evaluated against one model version in March may produce different runtime behavior against the next model version in October. &lt;a class="link" href="https://aembit.io/blog/aims-a-model-for-ai-agent-identity/" target="_blank" rel="noopener"
>Aembit&amp;rsquo;s AIMS reference model&lt;/a> and &lt;a class="link" href="https://saviynt.com/blog/ai-agent-lifecycle-management" target="_blank" rel="noopener"
>Saviynt&amp;rsquo;s lifecycle guidance&lt;/a> both treat a model upgrade as a re-attestation event: the agent&amp;rsquo;s identity has to be re-evaluated against the new model&amp;rsquo;s behavior before any privileges carry forward. There is no service-account analog. A Python service account does not need to be re-attested when you upgrade from Python 3.12 to 3.13, because the program is deterministic and an interpreter upgrade does not change its output. An LLM upgrade changes everything the agent does.&lt;/p>
&lt;p>&lt;strong>Multi-hop delegation confuses the principal.&lt;/strong> When a human asks an agent to do something, the agent may invoke a tool that calls another agent that calls another tool. The current OAuth 2.0 model handles &amp;ldquo;agent acting on behalf of user&amp;rdquo; for one hop. It does not handle three. The IETF &lt;a class="link" href="https://datatracker.ietf.org/doc/html/draft-oauth-ai-agents-on-behalf-of-user-00" target="_blank" rel="noopener"
>&lt;em>draft-oauth-ai-agents-on-behalf-of-user-00&lt;/em>&lt;/a>, published in 2025, extends OAuth specifically for this. The &lt;a class="link" href="https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization" target="_blank" rel="noopener"
>Model Context Protocol&amp;rsquo;s authorization spec&lt;/a>, finalized later in 2025, layers OAuth 2.1 with PKCE for the agent-to-tool boundary. The recurring failure mode is the confused deputy: the agent has authority X from the user and authority Y from its service identity, and the effective permission set should be the &lt;em>intersection&lt;/em>, not the union. Most production agent stacks still default to inheritance, which is the union. That has to flip.&lt;/p>
&lt;p>&lt;img src="https://mattgoodrich.com/posts/service-accounts-that-improvise/diagram-confused-deputy.png"
width="1077"
height="618"
srcset="https://mattgoodrich.com/posts/service-accounts-that-improvise/diagram-confused-deputy_hu7837024824725215595.png 480w, https://mattgoodrich.com/posts/service-accounts-that-improvise/diagram-confused-deputy_hu9240008007712307617.png 1024w"
loading="lazy"
alt="Default versus Target: the agents effective permission as the union of authorities versus the intersection of authorities"
class="gallery-image"
data-flex-grow="174"
data-flex-basis="418px"
>&lt;/p>
&lt;p>The reason all three of these are agent-specific is the property that links them: the agent&amp;rsquo;s execution path is non-deterministic. A service account does the same thing every time. An agent decides what to do at runtime, against inputs it does not fully control, with a model whose behavior moves with each release.&lt;/p>
&lt;h2 id="the-incidents-are-already-in-production">The Incidents Are Already in Production
&lt;/h2>&lt;p>Three things separate the &amp;ldquo;agent identity is a new concern&amp;rdquo; claim from theoretical hand-wringing. The incidents are already happening. The failure mode is consistent across them. And the controls that would have caught them are the boring ones nobody wired up.&lt;/p>
&lt;p>A representative sample from 2025 and early 2026:&lt;/p>
&lt;p>&lt;strong>&lt;a class="link" href="https://kenhuangus.substack.com/p/the-day-metas-ai-agent-broke-least" target="_blank" rel="noopener"
>Meta SEV1, March 2025&lt;/a>.&lt;/strong> Internal LLM agent with write access to a company engineering forum hallucinated access-control guidance about who could see what. Another employee acted on the hallucinated guidance. Sensitive data was exposed to thousands of engineers for nearly two hours. The agent had real authority; the input that confused it was internal text the agent had no way to validate.&lt;/p>
&lt;p>&lt;strong>EchoLeak / CVE-2025-32711, June 2025.&lt;/strong> Zero-click prompt injection in Microsoft 365 Copilot. Aim Security disclosed the chain that let an attacker exfiltrate confidential data from a Copilot session without the user ever interacting with the malicious content. First production-weaponized prompt injection against a major commercial AI system.&lt;/p>
&lt;p>&lt;strong>GitHub MCP &amp;ldquo;data heist,&amp;rdquo; May 2025.&lt;/strong> Invariant Labs demonstrated that a malicious public-repo issue, when ingested by Claude running with the GitHub MCP, would cause Claude to copy private repository contents into a public pull request. The agent&amp;rsquo;s GitHub identity had access to both. The prompt-injected instructions told it to use that access in a way the user never authorized.&lt;/p>
&lt;p>&lt;strong>&lt;a class="link" href="https://oddguan.com/blog/comment-and-control-prompt-injection-credential-theft-claude-code-gemini-cli-github-copilot/" target="_blank" rel="noopener"
>&amp;ldquo;Comment and Control,&amp;rdquo; April 2026&lt;/a>.&lt;/strong> Researchers showed that Claude Code Security Review, the Gemini CLI Action, and the GitHub Copilot agent could all be tricked into leaking &lt;code>GITHUB_TOKEN&lt;/code> or &lt;code>GITHUB_COPILOT_API_TOKEN&lt;/code> through prompt injection embedded in PR titles and comments.&lt;/p>
&lt;p>&lt;strong>GitGuardian&amp;rsquo;s 2025 numbers.&lt;/strong> 28.6 million secrets leaked to public GitHub in 2025, up 34% year over year. 1.2 million tied specifically to AI services, up 81% year over year. AI-assisted commits leak secrets at roughly twice the baseline rate.&lt;/p>
&lt;p>&lt;strong>&lt;a class="link" href="https://jfrog.com/blog/2025-6514-critical-mcp-remote-rce-vulnerability/" target="_blank" rel="noopener"
>CVE-2025-6514, mid-2025&lt;/a>.&lt;/strong> A flaw in the &lt;code>mcp-remote&lt;/code> OAuth proxy enabled remote code execution. Roughly 437,000 environments affected.&lt;/p>
&lt;p>None of these are about agents going rogue in the science-fiction sense. All of them are about agents executing real authority (the authority they were correctly granted under a normal service-account model) against inputs that turned out to be hostile. The identity discipline that would have caught them is the discipline I would have expected to be in place already: scope every credential to a task, never let an agent&amp;rsquo;s authority be the union of the user&amp;rsquo;s plus its own, and audit every tool call with the identity attached.&lt;/p>
&lt;h2 id="what-is-converging-as-practice">What Is Converging as Practice
&lt;/h2>&lt;p>Published guidance has begun to converge on a small set of patterns. They are practical, they reuse existing security infrastructure, and they treat the agent as a new member of the service-account family that needs the family discipline plus a small set of agent-specific additions.&lt;/p>
&lt;p>&lt;strong>Workload identity as the substrate.&lt;/strong> SPIFFE/SPIRE and OIDC federation are consolidating as the default agent-identity primitive. &lt;a class="link" href="https://www.hashicorp.com/en/blog/vault-enterprise-1-21-spiffe-auth-fips-140-3-level-1-compliance-granular-secret-recovery" target="_blank" rel="noopener"
>HashiCorp Vault 1.21&lt;/a> added native SPIFFE authentication; Vault 2.0 ships SPIFFE secrets-engine support. AWS, GCP, and Azure all expose workload identity federation that lets a SPIFFE-issued SVID become a short-lived cloud credential without long-lived API keys ever existing. Teleport ships &lt;a class="link" href="https://goteleport.com/docs/machine-workload-identity/" target="_blank" rel="noopener"
>Machine and Workload Identity&lt;/a> with the same X.509 SVIDs and a full audit trail. The substrate is not new; the new move is using it for agents.&lt;/p>
&lt;p>&lt;strong>Identity-aware tool gateways.&lt;/strong> Every tool call the agent makes flows through a gateway that verifies the agent identity, applies fine-grained authorization, and writes the call to an append-only audit log. &lt;a class="link" href="https://www.strata.io/resources/news/strata-identity-introduces-ai-identity-gateway-and-validation-sandbox/" target="_blank" rel="noopener"
>Strata&amp;rsquo;s AI Identity Gateway&lt;/a>, &lt;a class="link" href="https://www.databricks.com/blog/ai-gateway-how-connect-agents-external-mcps-securely" target="_blank" rel="noopener"
>Databricks Unity AI Gateway&lt;/a>, Teleport&amp;rsquo;s proxy, and open-source projects like &lt;a class="link" href="https://github.com/agentgateway/agentgateway" target="_blank" rel="noopener"
>agentgateway&lt;/a> (Solo.io&amp;rsquo;s contribution to the Linux Foundation) and IBM&amp;rsquo;s &lt;a class="link" href="https://github.com/IBM/mcp-context-forge" target="_blank" rel="noopener"
>ContextForge&lt;/a> all instantiate this pattern. The gateway is the choke point that turns &amp;ldquo;the agent did something&amp;rdquo; into a structured, attributable, auditable record.&lt;/p>
&lt;p>&lt;strong>Agent identity separated from invoking-user identity, with the effective permission set being the intersection.&lt;/strong> The IETF&amp;rsquo;s &lt;a class="link" href="https://datatracker.ietf.org/doc/html/draft-oauth-ai-agents-on-behalf-of-user-00" target="_blank" rel="noopener"
>&lt;em>draft-oauth-ai-agents-on-behalf-of-user-00&lt;/em>&lt;/a> formalizes this. The &lt;a class="link" href="https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization" target="_blank" rel="noopener"
>Model Context Protocol&amp;rsquo;s authorization spec&lt;/a> layers OAuth 2.1 with PKCE for the agent-to-tool boundary. The principle is straightforward: the agent should only be able to do things both the user &lt;em>and&lt;/em> its service identity are authorized for. Most production systems still default to inheritance, which is the union. The shift is from union to intersection.&lt;/p>
&lt;p>&lt;strong>Per-agent registries with purpose, owner, and scope.&lt;/strong> &lt;a class="link" href="https://saviynt.com/products/identity-security-for-ai" target="_blank" rel="noopener"
>Saviynt&amp;rsquo;s Identity Security for AI&lt;/a> and &lt;a class="link" href="https://www.sailpoint.com/products/agentic-fabric" target="_blank" rel="noopener"
>SailPoint&amp;rsquo;s Agentic Fabric&lt;/a> both ship an agent registry: every agent is registered with metadata at creation (purpose, owner, platform, model version, scope), and the registry drives lifecycle management. An orphan agent without an owner is flagged automatically. An agent whose stated purpose drifts from its observed behavior is flagged. The registry is the inventory the CSA survey says most organizations do not have.&lt;/p>
&lt;p>&lt;strong>Credential injection over credential embedding.&lt;/strong> &lt;a class="link" href="https://1password.com/blog/introducing-1password-unified-access" target="_blank" rel="noopener"
>1Password&amp;rsquo;s Unified Access&lt;/a> (with Runlayer and Natoma) addresses a specific MCP-era failure mode: credentials embedded in MCP server configs that then leak through prompt injection or PR commits. Credentials are referenced, not embedded, and resolved at connection time with hash-traceable retrieval. The &lt;a class="link" href="https://mattgoodrich.com/posts/1password-service-account-claude-secrets/" >same pattern at developer scale&lt;/a> is a dedicated 1Password vault read by a service account, with no AI credentials in &lt;code>.env&lt;/code> at all. This is the boring-and-essential operational fix the MCP-era incidents were begging for.&lt;/p>
&lt;p>&lt;strong>Runtime per-tool-call attribution.&lt;/strong> &lt;a class="link" href="https://permiso.io/blog/ai-agent-runtime-security" target="_blank" rel="noopener"
>Permiso&amp;rsquo;s runtime identity threat detection&lt;/a> for agents attributes every tool invocation back to an initiating user and agent identity, and detects behavioral anomalies against a learned baseline. This is closer to the new ground: human service accounts rarely needed runtime behavioral analytics because their behavior was deterministic. Agents do.&lt;/p>
&lt;p>None of those patterns require throwing out the existing IAM stack. They extend it. The agent enters the existing program as a new privileged service account class, and the new agent-specific controls sit alongside the long-standing NHI controls rather than replacing them.&lt;/p>
&lt;h2 id="where-the-answer-is-still-settling">Where the Answer Is Still Settling
&lt;/h2>&lt;p>Worth being honest about the parts that are not settled, because skipping this would oversell the synthesis above.&lt;/p>
&lt;p>&lt;strong>SPIFFE was not designed for non-deterministic workloads.&lt;/strong> &lt;a class="link" href="https://www.solo.io/blog/agent-identity-and-access-management---can-spiffe-work" target="_blank" rel="noopener"
>Solo.io&lt;/a> and others have noted that current SPIFFE/Kubernetes implementations treat all replicas of a workload as identical. That works for stateless web services. It works less well for agents whose behavior depends on prompt history, memory, and model version. Two instances of the same agent identity may produce wildly different actions on the same inputs, and the identity layer cannot currently distinguish them. The substrate is right; the granularity is not yet.&lt;/p>
&lt;p>&lt;strong>Model version as an identity property is real but operationally fuzzy.&lt;/strong> Aembit and Saviynt both treat model upgrades as re-attestation events. Nobody has converged on what re-attestation actually looks like. Re-run the entire eval suite? Re-evaluate just the high-risk action classes? Treat the new model as a different identity entirely, with its own permission set granted separately? The conceptual frame is converging. The operational answer is not.&lt;/p>
&lt;p>&lt;strong>Multi-hop delegation chains are still being formalized.&lt;/strong> OAuth 2.0 plus the IETF draft handles the human-to-agent boundary. MCP&amp;rsquo;s spec handles agent-to-tool. Neither cleanly handles agent-to-agent with multiple intermediaries. When an orchestrating agent calls a specialist agent that calls a tool that calls another agent, the identity audit trail is patched together by hand. The protocol work is happening; the production patterns are not yet settled.&lt;/p>
&lt;p>&lt;strong>The non-deterministic path itself does not fit current &amp;ldquo;allowed or denied&amp;rdquo; binaries.&lt;/strong> Most authorization engines answer yes or no. An agent&amp;rsquo;s correct authorization decision sometimes depends on what just happened: the conversation history, the most recent tool output, the confidence of the model&amp;rsquo;s classification of the current step. Conditional, stateful, history-aware authorization is in the research literature (Cedar policies, OPA with state) but it is not the default. Production stacks are still doing static policy evaluation against requests that should probably be evaluated against trajectories.&lt;/p>
&lt;p>The honest version is that the framework is converging on workload identity plus agent-specific extensions, and the agent-specific extensions are mostly still being designed.&lt;/p>
&lt;h2 id="where-this-lands">Where This Lands
&lt;/h2>&lt;p>After the research, the answer is the boring one and the interesting one at the same time. Agent identities are a new sub-class of non-human identity, and the new sub-class needs about ten percent new controls on top of about ninety percent existing NHI hygiene that most organizations have not implemented yet.&lt;/p>
&lt;p>The ten percent that is genuinely new is genuinely new. Prompt injection has no service-account analog. Model version is a moving identity property. Multi-hop delegation with intersection-not-union semantics is a protocol problem still being solved. Those parts need their own controls, their own tooling, and their own threat model.&lt;/p>
&lt;p>The ninety percent that is the same is the harder problem in practice, because it is the work most organizations have been deferring for a decade. The agent rollout does not let you defer it any longer. Short-lived workload identities, per-action scoping, intersection-not-union delegation, audit on every call, an inventory with owners and purposes for every identity in the system: that is the work, and you cannot do agent identity well without doing non-human identity well first.&lt;/p>
&lt;p>What that authorization model looks like (how the permission grants are structured, how the policy is enforced, how the trust ladder progresses) is the subject of the &lt;a class="link" href="https://mattgoodrich.com/posts/agents-need-capabilities-not-roles/" >follow-on post&lt;/a>. The shorter answer to the question this post set out to investigate is the one that fits on a sticky note. The agent identity is a service account that improvises. The discipline you need is half a service-account discipline you should already have, and half a set of new controls for the part that improvises.&lt;/p></description></item></channel></rss>