How AI Agents Get Impersonated (and How to Stop It)
Let's define "impersonation" first, because it gets used two ways here, and it's worth separating them once rather than relitigating it in every section. In identity systems it has a narrow meaning: RFC 8693 §1.3 describes a token where, as far as the resource server is concerned, it is dealing with the impersonated party, as opposed to delegation, where both identities stay visible. Note that the RFC is describing a feature, not an attack. Everywhere else, including most of this post, impersonation just means an agent's identity got exploited: stolen, spoofed, borrowed, or stretched past what it should cover. Not every attack below meets the RFC's bar, but all of them land the same way: an action under an identity it shouldn't have. Here are six ways that happens, and what closes each one.
1. Credential theft
An agent's credential (an API key, an OAuth token, a service-account secret) gets exfiltrated: through a logged prompt, a leaked .env file, a compromised CI pipeline, or a dependency that phones home. Whoever holds it can now call every API the agent could call, and every log line will say the agent did it, because as far as the resource server is concerned, it did. The credential itself is genuine, so there's no identity check that would have caught this. It's a theft problem before it's an identity problem.
GitGuardian's State of Secrets Sprawl 2026 report found nearly 29 million new hardcoded secrets on public GitHub in 2025, a 34 percent year-over-year jump. Agent-specific tooling shows up directly in the numbers: the same report found 24,008 unique secrets in MCP-related config files on public GitHub in 2025, of which 2,117 verified as still valid. Agents make the underlying issue worse in a specific way: they need runtime access to credentials to act autonomously, so the credential has to live somewhere reachable at inference time, not locked in a vault a human unlocks once a day.
What closes it: no long-lived secret reachable at inference time. Give the workload an identity it can prove without a static secret (mTLS client certificates, SPIFFE, cloud workload identity federation, or private_key_jwt with a key that never leaves the runtime), and let everything the agent actually carries be a short-lived, narrowly scoped token minted from that identity for this run. A stolen five-minute token is a small problem; a stolen key that mints them is not. Pair it with secret scanning and rotation, because those 2,117 valid MCP secrets were all findable.
2. Fake agent registration
Before an agent can act, something has to trust it enough to grant it a credential in the first place. OAuth 2.0 Dynamic Client Registration (RFC 7591) lets a caller self-register as a new OAuth client. Where that endpoint accepts registrations with no verification of who's asking, an attacker can register a client that looks, to the authorization server, exactly as legitimate as your real agent, then use it to phish for consent or quietly sit in the client list until it's useful.
This is why the MCP spec's November 2025 authorization update points toward Client ID Metadata Documents (CIMD) over DCR: a metadata document hosted at an HTTPS URL the client controls, so the registering identity can be checked against something instead of taken on its word, with DCR kept as a fallback rather than the default path.
What closes it: don't accept self-asserted agent identity as sufficient for trust. Require a verifiable registration artifact (CIMD, a signed manifest, an admin-approved client) before an agent gets a credential at all, not just before it gets a scope. CIMD verifies the document, not the process presenting it; the MCP spec itself notes that anyone can present a legitimate client's metadata URL together with a localhost redirect. For a confidential agent, pair it with private_key_jwt so the credential proves possession of a key, not just a URL. Where DCR has to stay in the picture for compatibility, keep open registration off by default, rate-limit the endpoint, and restrict it to redirect URI schemes you explicitly trust. (On Zitadel, dynamically registered clients share one project audience, so tell them apart by client_id or azp, never by aud alone.)
3. Agent-to-agent spoofing
Multi-agent systems don't create a new class of target; services have trusted each other's self-description, or forwarded a token blindly to the next hop, for as long as there have been microservices. What changes is that the peer is picked at runtime, often from a discovery document the agent just read, and the trust decision is made by a model instead of a config file. In an A2A-style workflow, one agent might approve a payment, escalate a request, or hand off a task based entirely on which agent claims to be asking. If Agent B can convince Agent A that it's Agent C, a trusted peer, Agent A will act on that claim without ever meeting the real Agent C.
The A2A protocol, now at v1.0 with more than 150 supporting organizations and governed under the Agentic AI Foundation alongside MCP, explicitly does not define an authorization framework. It standardizes how an agent advertises which credentials it accepts (API keys, bearer tokens, OpenID Connect, mutual TLS) in its Agent Card. Whether the caller is who the credential says, and which agent may act on which skill using whose data, is left to whoever implements it. Skip that step and you have a protocol for two agents to talk securely while trusting each other for the wrong reasons.
What closes it: authenticate the agent, then separately authorize the specific skill or action, scoped per caller. "This agent has a valid identity" and "this agent may trigger this action" are two different checks, and A2A only tells you which credentials to expect for the first one.
4. Token reuse after the task ends
A token issued for one run of an agent doesn't stop being valid just because the run is over, unless something enforces that. If a task-scoped token outlives the task, whoever holds it (the original agent misbehaving, a compromised sidecar, a logged copy of the request) can replay it later, and the resource server has no way to tell the difference between "the agent, still working" and "the agent's old credential, reused."
What closes it: bind token lifetime to task lifetime, not to a calendar default. "Expires when the run finishes" is a property you have to design for; "expires in a day" is what you get by not designing for it. In practice that means short expiry with refresh gated on the run still being alive, and revocation (RFC 7009, or a revocable delegation object) when it ends. Sender-constrained tokens (DPoP, RFC 9449, or mTLS-bound tokens, RFC 8705, both recommended by the OAuth Security BCP, RFC 9700) add a second layer: a replayed token is useless without the private key bound to it.
5. Confused deputy via unnarrowed delegation
This one doesn't require stealing anything. An agent legitimately holds a broad grant (say, an employee's OAuth scope to Google Drive) because narrowing it down to "these three folders, this run" was more work than handing over the whole thing. A prompt injection, a bad instruction, or a bug then gets the agent to use that grant somewhere the task never intended. Nothing about the agent's identity is in question here; it's acting exactly as itself, just with more authority than the task justified. The result still lands as an action nobody meant to authorize.
What closes it: delegation, not inherited scope. RFC 8693's actor pattern (sub for the user, act for the agent, scope narrowed at issuance) means the agent never holds more than the task needs, so even a successful injection has a small blast radius. We've written about this pattern in more depth in our post on AI agent identity.
6. Borrowed credentials by design
The most literal version of this list isn't a sophisticated attack at all: it's a personal access token pasted into an agent's environment variables at setup, because that was the fastest way to get it working. The credential is the employee's. The scope is whatever that token was cut with, often everything the employee can reach. And every log line the agent generates says the employee did it. This is RFC 8693's definition of impersonation, playing out by default rather than by attack: the resource cannot tell the agent apart from the person it borrowed.
Nobody designed this as an attack, which is exactly the problem: it's built into the architecture from day one, not something an attacker had to introduce.
What closes it: give the agent its own identity, even if it's a dedicated service account, and route it through a delegation instead of a shared secret. If migrating off a shared PAT sounds like a project, it is one, but it's the first project, not an optional one.
The pattern underneath all six
What ties these together isn't that an identity is always ambiguous; most of the time it isn't. It's that something downstream trusted a claim it couldn't actually verify: a token it couldn't check for freshness, a registration it couldn't check for authenticity, an agent-to-agent claim it couldn't check for authorization, a scope it never narrowed. None of it requires breaking cryptography. It requires finding the place where verification was assumed instead of enforced.
That's why the fix is a short list, and most of it repeats across the six: an identity the agent doesn't share with anyone else, a registration that can be verified before a credential is issued, authorization per caller and action rather than authentication alone, a delegation that's recorded and narrowed rather than inherited wholesale, tokens that expire on the task's schedule instead of the calendar's, and an audit trail that names the agent specifically, not "the service account" or, worse, the human who happened to be logged in when it ran.
Zitadel ships RFC 8693 token exchange today, with the act claim identifying the acting agent and scope reduction at issuance, plus an audit trail you can stream to your SIEM. We're building the next piece, agents as first-class principals with delegations stored as revocable objects, in the open as part of Zitadel's next generation. If you're wiring up agents this quarter and want the delegation pattern instead of the shared-credential one, the token exchange guide is the place to start.
Sources and further reading
GitGuardian: State of Secrets Sprawl 2026
RFC 8693: OAuth 2.0 Token Exchange, §1.3 on delegation vs. impersonation (IETF)
RFC 7591: OAuth 2.0 Dynamic Client Registration Protocol (IETF)
RFC 9700: OAuth 2.0 Security Best Current Practice (IETF)
RFC 9449: OAuth 2.0 Demonstrating Proof of Possession (DPoP) (IETF)
RFC 8705: OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens (IETF)
RFC 7009: OAuth 2.0 Token Revocation (IETF)
OAuth Client ID Metadata Document (IETF draft)
Model Context Protocol: Authorization, 2025-11-25
Linux Foundation: A2A Protocol Surpasses 150 Organizations (April 2026)
Zitadel: Dynamic Client Registration guide · OAuth token exchange guide · audit trail
Zitadel: AI Agent Identity
