Author: Christopher Emerson

  • Why do AI agent attacks keep going for the credential, not the model?

    Short answer: because the credential is both the easier target and the bigger prize. Across the major AI agent security incidents of 2025 and 2026, attackers did not need to defeat the model. They went after the standing OAuth tokens, API keys, and environment credentials the agent already held, then used the agent’s own legitimate access to do the damage. The structural fix is to keep reusable app master credentials and refresh tokens out of the agent’s environment: deliver a scoped grant through the human, check it on every call, and keep the authorization decision somewhere no injected prompt can reach.

    Watch: why standing credentials set the blast radius in 44 seconds

    The Stolen Key, a 44-second film on why standing credentials set the blast radius for AI agent attacks.

    Transcript: One compromised AI chat integration exposed standing OAuth access across hundreds of companies. The pattern keeps repeating: broad credentials sit inside automated channels before an attack begins. Then untrusted content becomes an instruction, and the agent uses authority it already holds. User-mediated authorization changes the path: the human chooses the scope, duration, and grant. Every call is checked. The agent cannot grow its own access. A stolen key stops being a master key.

    What happened in the biggest AI agent credential breaches?

    The clearest enterprise-scale example in this set barely mentioned a model at all. Between August 8 and 18, 2025, a threat group Google tracks as UNC6395 used stolen OAuth and refresh tokens associated with the Drift AI chat agent to access customer Salesforce instances at scale. Google told The Hacker News that more than 700 organizations may have been potentially impacted. Companies that publicly confirmed exposure included Cloudflare, Palo Alto Networks, Zscaler, Cato Networks, Elastic, and Google Workspace customers. Salesloft eventually took Drift offline entirely. And what did the attackers harvest from those CRM instances? More credentials: AWS keys, passwords, and access tokens stored in support cases.

    One AI chat agent integration held durable OAuth access and refresh tokens into hundreds of companies. Nobody had to jailbreak a model. The tokens were valid, broad, and reusable. AgentAdmit would not have sat inside Salesloft’s token store, so this is not a literal intercept case. It is the clearest public example of why durable agent and integration credentials can turn one compromise into an enterprise-scale campaign.

    The rest of the 2025 and 2026 incident record repeats the theme with different mechanics:

    • OpenAI Codex, disclosed March 2026. BeyondTrust researchers hid a command injection inside a Unicode-obfuscated git branch name. The payload stole the GitHub token Codex was holding. OpenAI classified it Critical P1 and remediated the shell-escape path.
    • Claude Code, CVE-2026-21852. Check Point Research showed that a repository settings file could override the ANTHROPIC_BASE_URL environment variable, so the agent sent its API key to an attacker’s server before the user ever saw a trust prompt. Opening the folder was enough. The record carries a CVSS v4.0 score of 5.3 Medium and an NVD CVSS v3.1 score of 7.5 High. It remains the cleanest example of an automated channel silently redirecting a credential.
    • Amazon Q Developer, July 2025. AWS’s own security bulletin traced the incident to an “inappropriately scoped GitHub token” in a build configuration. With it, an attacker committed a system-wipe prompt that shipped to users in release 1.84.0. The payload failed only because of a syntax error.
    • Amazon Q Developer again, June 2026. AWS disclosed that a malicious workspace could automatically execute project-configuration commands after the user trusted the workspace. Wiz Research found that an attacker-controlled MCP process could then inherit the developer’s live AWS credentials, including session tokens. The issue is CVE-2026-12957.
    • GitHub Copilot Chat “CamoLeak,” disclosed October 2025. Legit Security used GitHub’s own invisible-comment feature to inject instructions into any user’s Copilot session, then exfiltrated private repository contents through GitHub’s own image proxy. Scored 9.6 in the disclosure. The researcher’s key observation: “Copilot operates with the same permissions as the user making the request.”
    • Salesforce Agentforce “ForcedLeak,” CVSS 9.4. Noma Security planted instructions in a web form field; the agent followed them and sent CRM data to an expired domain that was still on Salesforce’s allowlist. The domain cost the researchers five dollars.
    • GitHub Agentic Workflows “GitLost,” July 2026. Noma Labs posted a crafted issue in a public repository and manipulated GitHub’s own agent into reading a private repository and publishing its contents as a public comment. No credential was stolen in this case. The damage came from authority the workflow already held. Adding the single word “Additionally” was enough to get past the guardrails.

    What failure pattern do these incidents share?

    Strip away the vendor names and the same four steps appear every time.

    1. The agent already holds broad standing authority. An OAuth token valid for months. An API key in an environment variable. The full permissions of whichever user is asking.
    2. That authority is automatically available inside the runtime. A redirect, an environment variable, a config file, a build pipeline, or a workspace-wide identity makes it usable without a new human decision.
    3. Untrusted content became an instruction. A branch name, a PR description, a web form, a public issue. Agents read everything, and everything they read can steer them.
    4. Nothing independent stood between the agent and the blast radius. No per-call check that could shrink the credential’s power, no human-only step for sensitive moves, no fast way to see and kill one agent’s access.

    Steps 1 and 2 are the ones that decide severity. GitGuardian made the same point in an August 2026 analysis of the year’s agent incidents: “The exploit created the opening. But it was the stolen credential that extended the attacker’s access.” CrowdStrike’s 2026 Global Threat Report put it even more bluntly in a section header: “Prompts are the New Malware.”

    Why don’t guardrails and permission prompts stop this?

    Because guardrails are probabilistic and credentials are deterministic. GitLost fell to a one-word change in the injected prompt. Model-side defenses reduce the odds of a successful trick. If a trick lands, the authority already available to the agent decides what happens next.

    Permission prompts have a different problem: people stop reading them. Anthropic’s own engineering write-up on sandboxing reported that users approved roughly 93% of permission prompts, and noted that the more approvals a user sees, the less attention they pay to each one. A consent step that fires dozens of times a day is not a consent step. It is a reflex.

    The numbers on standing credentials are just as uncomfortable. GitGuardian’s State of Secrets Sprawl 2026 counted 1,275,105 AI-service secrets exposed on public GitHub in 2025, up 81% year over year, with more than 24,000 unique secrets sitting in MCP configuration files. Each one of those is step 1 of the pattern, waiting for steps 3 and 4.

    What architecture takes the credential off the attack path?

    Change where the credential travels and how long it lives. That is the design AgentAdmit ships, and it is called user-mediated authorization (patent pending). It complements standards like OAuth rather than replacing them.

    The mechanics, mapped against the four steps above:

    • The credential is delivered to the human, not the agent. The user requests a connection inside the app they already trust, chooses the exact scopes and duration, and receives a single-use connection token. They hand it to their agent themselves. There is no redirect, no callback, no webhook, no automated path between the app and the agent for an injected prompt to exploit.
    • Grants are scoped and time-bounded. An agent gets the actions the user picked and nothing else, for the duration the user picked and no longer. There are no refresh tokens; when access ends, a human renews it or it stays ended. A stolen grant limited to three actions and a chosen duration is a very different asset from a Drift-style token that covers a whole CRM for months.
    • Every call is checked. Access is validated against the grant on each request, so an out-of-scope action fails at the moment it is attempted, not after the audit. Users can also set usage limits on a grant, and an agent cannot raise its own limits.
    • Revocation is immediate and per-agent. The user sees each connected agent, what it is allowed to do, and what it actually did, and can cut off one agent without touching anything else. An API-key caller can tighten automated protections, but weakening them requires a human presence ceremony.

    None of this stops a prompt injection from landing. Filters still matter. What changes is containment: no reusable app master credential needs to sit in the agent runtime, the agent cannot grow its own grant, and every call is checked against what the user already approved. The trick still happens. The blast radius shrinks to the scope, duration, and usage limits of that grant.

    FAQ

    Are AI agent breaches caused by weaknesses in the models themselves?

    In the incidents above, severity was set by what the agent could already reach, not by whether the model was “broken.” Some attacks did exploit instruction-following behavior or weak guardrails, but stolen OAuth tokens, over-scoped build tokens, and inherited cloud credentials decided the blast radius.

    Would better prompt-injection filters have prevented these incidents?

    They would have reduced the odds, not the consequences. GitLost bypassed GitHub’s guardrails with a one-word change, and filters do nothing about a token stolen from an environment variable. Filters are worth running, but the blast radius is set by what the agent can reach when a trick succeeds.

    What is user-mediated authorization for AI agents?

    An authorization pattern where the credential is delivered to the human instead of the agent. The user selects scopes and duration, receives a single-use connection token inside the app, and gives it to their agent out of band. The authorization decision lives outside the agent’s execution context, so an injected prompt cannot trigger or escalate a grant.

    How does scoping limit the damage from a compromised agent?

    A scoped grant means a hijacked agent can only misuse the specific actions the user approved, for the time window the user approved. Combined with per-call validation, usage limits, and per-agent revocation, that can turn a potential mass breach into a contained, visible, and quickly reversible incident.

    If you are building an app that AI agents will connect to, AgentAdmit gives your users scoped, revocable, auditable agent access with the credential delivered to the human. Start in Test Mode at agentadmit.com.

    Related reading: Prompt injection is an authorization problem, What is user-mediated authorization for AI agents?, and Can an AI agent approve its own permission request?

  • Prompt Injection Is an Authorization Problem, Not Just a Model Problem

    Short answer: Prompt injection cannot be fully solved at the model layer, so you cannot rely on the agent refusing malicious instructions. What contains the damage is authorization: if an agent can only ever do a few narrow things, and it cannot expand its own access, then a successful injection has very little to work with. Scope is your last line of defense, because it is the one that does not depend on the agent behaving.

    Can prompt injection be fixed at the model level?

    Not completely, and the model builders say so. Anthropic, reporting on its browser-agent defenses, wrote that even after major gains to a roughly 1 percent attack success rate, “no browser agent is immune to prompt injection,” and shared its results “to demonstrate progress, not to claim the problem is solved.” Palo Alto Networks Unit 42 reported in early 2026 that indirect prompt injection, where hidden instructions are planted in content the agent reads, is “no longer merely theoretical but is being actively weaponized” in the wild, with observed goals including unauthorized transactions and sensitive information leakage.

    The reason is structural. An AI agent has to read untrusted content to be useful, and it cannot perfectly separate instructions it should follow from instructions buried in that content. Detection and training reduce the rate. They do not drive it to zero.

    If you cannot stop injection, what actually limits the damage?

    The blast radius. Once you accept that some injections will land, the question stops being “how do we make the agent perfect” and becomes “what can a compromised agent actually reach.” That is an authorization question, not a model question.

    Consider two agents that both get hijacked by an injected instruction. The first holds a broad, standing API key. The second holds a grant scoped to reading one resource, that expires, and that it cannot widen on its own. The same injection lands on both. On the first it can exfiltrate or destroy widely. On the second it can do almost nothing. The difference was never the model. It was the access.

    What do real incidents show about scope as a control?

    They show that standing, over-broad access is what turns an injection into a breach:

    • The GitHub MCP “toxic agent flow” (2025). A benign-looking request combined with a poisoned public issue led an agent to leak private repository data, all through the same over-broad token it already held. The injection supplied the intent; the broad token supplied the reach.
    • EchoLeak (CVE-2025-32711). A zero-click prompt-injection flaw in Microsoft 365 Copilot could cause sensitive data to be exfiltrated with no user action at all. When the agent already has standing access, no human click is even required.
    • In-the-wild indirect injection (Unit 42, 2026). Attackers embedded instructions in web content to drive unauthorized actions. What decides the outcome is what the agent was permitted to do when it read the poisoned page.

    What does “authorization as the last line of defense” require?

    Three properties, all independent of whether the agent behaves:

    • Least privilege by default. Grant only the specific actions and resources the task needs, so there is little for a hijacked agent to abuse.
    • No self-service escalation. The agent must not be able to widen its own access. If more access requires a fresh decision by the person, an injected instruction has no path to more power. A request beyond scope should return an error and route back to the human.
    • The authorization decision lives outside the agent. If granting or expanding access happens in a channel the agent cannot operate, then an injected instruction cannot trigger it. This is the core idea behind user-mediated authorization: the person authors the grant in the app’s own session and the agent never has a programmatic path to create or escalate one.

    None of this replaces model-level defenses or standards like OAuth and MCP. It sits underneath them as the control that still holds when the model is fooled, which the model builders tell us it sometimes will be.

    Frequently asked questions

    Is prompt injection an authorization problem or a model problem?

    Both, but the durable control is authorization. The model layer reduces how often injection succeeds; it cannot eliminate it. Authorization decides how much damage a successful injection can do, which is why scope is the control that still holds when the model is fooled.

    Can you prompt-engineer your way out of prompt injection?

    No. Model builders including Anthropic state plainly that no browser agent is immune and the problem is not solved. Better prompts and classifiers lower the rate but leave a non-zero miss rate, so you have to assume some injections land and limit what they can reach.

    How does least-privilege access stop prompt injection damage?

    It shrinks the blast radius. A hijacked agent can only do what it was authorized to do, so an agent scoped to a single read cannot delete data or move money no matter what a malicious instruction tells it. The narrower and more revocable the grant, the less an injection is worth.

    Why does keeping the authorization decision outside the agent matter?

    Because an injected instruction is something the agent acts on. If the agent could grant or expand its own access, injection could drive that escalation. When the grant is authored by the person in a channel the agent cannot reach, there is no path from a malicious prompt to more access.

    AgentAdmit is the authorization layer for AI agents, built so a hijacked agent cannot widen its own access and the authorization decision lives outside the agent’s reach. Learn more at agentadmit.com.

    Related reading: What is user-mediated authorization for AI agents?, What is the Context Access Divide?, and MCP security: how to let an AI agent access user data safely, Can an AI agent approve its own permission request?, AI agent authorization vs API keys.

  • AI Agent Authorization vs. API Keys: What’s the Difference?

    Short answer: An API key is a single long-lived secret that grants broad, standing access and says nothing about who is using it or what they are allowed to do. Agent authorization replaces that with a scoped, time-limited, revocable grant tied to a specific user and a specific agent, checked on every call. The difference matters because an AI agent reads untrusted content and takes autonomous actions, so a broad key it holds forever is a much bigger liability than the same key sitting in a script.

    Why do so many AI agents run on static API keys today?

    Because it is the path of least resistance. Most services expose a plain API and no way to grant an agent narrow, revocable access, so developers paste a static API key or personal access token into an environment variable and move on. A 2025 security scan of thousands of MCP (Model Context Protocol) servers found that, of the servers requiring credentials, roughly 53 percent relied on static API keys or personal access tokens and only about 8.5 percent used OAuth. Security researchers have taken to calling these long-lived, over-scoped secrets “the God key,” and have described MCP servers as the new shadow IT precisely because they “operate with broad privileges” and “rely on weak credential models such as long-lived static secrets.”

    The key works, which is the problem. It is invisible to the user after setup, it rarely expires, and it usually carries far more access than the task needs.

    What is actually wrong with giving an agent an API key?

    Three things, and each gets worse when the holder is an AI agent rather than deterministic code:

    • It is over-broad. A key is typically all-or-nothing. The agent that only needs to read your notes can usually also delete them. There is no per-action, per-resource limit baked into the secret.
    • It is standing and long-lived. The key keeps working until someone remembers to rotate it. There is no built-in expiry that forces the person back into the loop.
    • It erases attribution. A shared key tells the service nothing about which user or which agent is behind a given call. When something goes wrong, there is no clean record of who authorized what. Security researchers describe this as the moment “user attribution is lost and least privilege controls break down.”

    An AI agent amplifies all three. It processes untrusted inputs, it can be steered by prompt injection, and it acts on its own. A broad, permanent, unattributed key in the hands of something that can be manipulated is a standing liability, not a convenience.

    How is scoped agent authorization different?

    Agent authorization treats access as a narrow, revocable grant instead of a shared secret. The properties that matter:

    • Scoped. The grant names exactly which actions and resources are allowed (for example, read notes but not manage the account). A request outside that scope is refused.
    • Time-limited on the user’s terms. The grant lasts as long as the person chose, an hour, a week, or until they revoke it. Unlike a forgotten key, ending access is a decision the user owns, and shorter durations add deliberate friction for sensitive tasks.
    • Per-user and per-agent. The grant is tied to a specific person and a specific agent, so every call is attributable and the audit trail names who authorized it.
    • Revocable in isolation. The person can revoke one agent’s access without disturbing anyone else’s, and the change takes effect on the agent’s next call.

    Note that OAuth on its own does not fully close the gap for agents. In a standard authorization-code flow the token’s subject is the human, so the resource server cannot tell the user from the agent acting for them, and there is no separate audit trail for the agent. Naming the agent as a distinct, separately-authorized party is the piece that has been missing.

    What does replacing the API key look like in practice?

    With user-mediated authorization, the person opens a “Connect Your AI Agent” flow inside the application’s own session and picks the scopes and the duration. The app issues a single-use, time-limited connection credential, delivers it to the person (not to an agent endpoint), and the person hands it to their agent. The agent exchanges it for a scoped, revocable access token that is validated on every call. The static key in the environment variable, long-lived and all-or-nothing, is replaced by a grant the user authored and can revoke.

    This complements standards like OAuth and protocols like MCP rather than replacing them. MCP tells the agent what a service can do. The authorization layer decides whether this agent, for this user, is allowed to do it, and keeps that grant scoped, attributable, and revocable.

    Frequently asked questions

    Are API keys bad for AI agents?

    They are risky as the primary access model. A static API key is long-lived, usually over-scoped, and unattributed, so an agent that holds one has broad standing access that no one is watching. That is a poor fit for software that processes untrusted input and acts autonomously. Scoped, time-limited, revocable grants are the safer alternative.

    Why not just use OAuth for AI agents?

    OAuth is a strong foundation, but in a standard flow the token represents the human, so the service cannot distinguish the user from the agent acting for them, and there is no separate audit trail for the agent. Agent authorization adds a per-user, per-agent, scoped grant on top of that foundation.

    How do you give an AI agent least-privilege access?

    Grant only the specific actions and resources the task needs, attach an expiry, tie the grant to the user and the agent, and make it revocable on its own. Then validate every call against that scope rather than trusting a single broad secret.

    What is the difference between an API key and an access token here?

    An API key is a standing secret that usually grants broad access indefinitely. The scoped access token described here is narrow, expires, is tied to a specific user and agent, and can be revoked without affecting other connections.

    AgentAdmit is the authorization layer for AI agents: scoped, time-limited, revocable access the user controls, in place of a static key. Learn more at agentadmit.com.

    Related reading: What is user-mediated authorization for AI agents?, How to let an AI agent access a user’s account safely, and MCP security: how to let an AI agent access user data safely, Can an AI agent approve its own permission request?.

  • What Is Caller-Identity Consent for AI Agents?

    Short answer: Caller-identity consent means one API surface can serve several kinds of caller, a signed-in person, the application’s own built-in AI, and an external AI agent acting for a user, and let the data owner consent to each kind independently. Granting one never grants another, and any combination is allowed. It matters because roles and scopes were built to tell humans apart, not to ask “is it a person, our own AI, or someone’s external agent,” which is now the question that decides whether data should be shared.

    Watch: caller-identity consent in 37 seconds

    Three Callers, One Door, a 37-second film on caller-identity consent from AgentAdmit.

    Transcript: One door to your data. Three very different callers: a person, the app’s own AI, and an outside agent. Roles and scopes were built to tell humans apart. They cannot even ask which kind is calling. Caller-identity consent reads the caller’s class from the structure of its credential. A class it cannot fake. Three consent states. One endpoint. No inheritance. Changing one never changes another. Any combination the data owner wants. AgentAdmit.

    What is caller-identity consent?

    Picture a fitness coaching app. A member’s workout data can be reached three different ways: their coach opens it in the dashboard (a human), the app’s own built-in AI generates a summary of it (the platform’s internal AI), and the coach points their own external AI agent at it to prepare for a session (an outside agent acting for the coach). Those are three architecturally distinct callers hitting the same data through the same API.

    Caller-identity consent lets the data owner decide on each one separately. The member might let their coach view the data and let the in-app AI summarize it, while blocking all external agents. Or allow an external agent to read it while denying the platform’s own AI. Each decision is independent, and changing one never changes another. That is the core property: three consent states, one endpoint, no inheritance between them.

    Why don’t roles or scopes already handle this?

    Because they answer a different question. Role-based access control and OAuth scopes were designed to distinguish one human user from another, or to limit what a single credential can do. They do not express “a person may see this, but our AI may not,” or “an external agent may read this, but our own AI may not.” Those distinctions are about the class of caller, not the identity of a user or the breadth of a token.

    There is also a blind spot. An application’s own internal AI usually never passes through the authorization layer at all, because it is just the app’s own code reading the app’s own data. So there is often nothing to attach a consent decision to for that class. Caller-identity consent makes the internal-AI class a first-class decision the data owner can actually control, alongside humans and external agents.

    How does the caller class stay un-spoofable?

    Classification happens before any consent check, and it is derived from the structure of the credential, not from anything the caller can set. A standard login session, the application’s own internal service credential, and an external agent’s access token each look structurally different (by token format, prefix, signing method, issuer, or session context). The system reads those structural traits to decide the class. The caller cannot self-select or spoof it, and cannot claim to be a person while behaving as an agent.

    Only after the class is fixed does the system evaluate that class’s own consent path, and each path reads only its own setting. No path inherits or even looks at another path’s preference. This is what keeps “allow the human, deny the AI” from silently leaking into “allow everything.”

    How does AgentAdmit implement caller-identity consent?

    AgentAdmit provides the consent-differentiation engine and the storage behind it: an independent consent state per class per data owner, an immutable consent ledger for audit, and APIs to read, set, and export those states. On the request path it validates external agent tokens (the class it issues) and enforces that class’s consent and scope directly. For the human and internal-AI classes, which live inside the application’s own boundary, the application classifies the caller from the credential and checks the matching consent path through the same engine, so all three decisions stay consistent and independent.

    For the data owner’s side, the AgentAdmit React SDK ships a drop-in consent panel with three independent switches, wired through the application’s own backend so credentials never reach the browser. The result is the pattern described above, delivered as components and APIs rather than something each app rebuilds from scratch.

    The switches themselves are protected against the caller they govern. Because a computer-use agent could try to flip the very consent toggles that restrict it, an app can require that any change to a data owner’s consent settings carry fresh proof of human presence, meaning a confirmation the agent cannot produce from where it runs (AgentAdmit implements this with WebAuthn user verification from a pre-registered authenticator; an approval on a separate device satisfies the same property). The same requirement can be applied when a grant elevates an agent’s existing scopes. The decision to allow a class of caller stays a human decision, made through a ceremony the caller class in question cannot complete.

    This complements standards like OAuth and protocols like MCP. They authenticate the caller and describe what a service can do. Caller-identity consent adds the layer that asks, for this specific class of caller, whether the data owner agreed to this at all.

    Is caller-identity consent limited to three classes?

    No. Three (a human session, the application’s own AI, and an external agent) is the common set today, but the model is not fixed at three. The same design, classify the caller from the structure of its credential and then evaluate that class’s own independent path, extends to additional classes as they emerge, without disturbing the classes already in place. A natural example is a verified-agent class: as standards like Web Bot Auth let agents cryptographically prove their identity, a data owner may want to allow verified agents while still denying unverified ones, which is a separate decision from a blanket external-agent switch. A delegated-user class, for one person acting on behalf of another, is another. The point is that the independent-path model generalizes rather than hard-coding the number of caller classes.

    Frequently asked questions

    What is caller-identity consent in one sentence?

    It is the ability for a data owner to grant or deny access independently for each class of caller, a human session, the application’s own AI, and an external AI agent, at the same API endpoint, with no class inheriting another’s permission.

    How is this different from OAuth scopes or roles?

    Scopes and roles distinguish users and limit what a token can do. They do not express consent per class of caller, and they usually do not cover an application’s own internal AI at all, because it never traverses the authorization layer. Caller-identity consent adds that per-class, no-inheritance decision.

    Can a caller pretend to be a different class to get access?

    No. The class is derived from structural characteristics of the credential before any consent check, not from anything the caller supplies. A requestor cannot self-select its class, so an external agent cannot present itself as a human session to inherit a person’s access.

    Does the data owner have to allow all three, or none?

    Neither. Every combination is valid: none, one, two, or all three. The decisions are independent, so a data owner can allow a human while denying both AI classes, allow an external agent while denying the platform’s own AI, or any other mix.

    Can there be more than three caller classes?

    Yes. Three is the common set, but the independent-path model is not limited to three. New classes, for example a verified-agent class as agent-identity standards like Web Bot Auth mature, or a delegated-user class for one person acting on behalf of another, can be added the same way: classify from credential structure, then evaluate that class’s own consent path, without changing the classes already in place.

    AgentAdmit is the authorization layer for AI agents, including independent, per-caller-class consent the data owner controls. Learn more at agentadmit.com.

    Related reading: What is user-mediated authorization for AI agents?, What is the Context Access Divide?, and MCP security: how to let an AI agent access user data safely, Can an AI agent approve its own permission request?.


  • Can an AI Agent Approve Its Own Permission Request?

    Short answer: Yes. If an approval screen is reachable from the place an AI agent runs, a browser tab it drives or a dialog on the machine it controls, then a compromised or prompt-injected agent can click “Approve” by itself. A confirmation click proves that something clicked, not that a human weighed the decision. The durable fix is to move the authorization decision out of the agent’s reach, so the grant is authored by the person in a channel the agent cannot operate.

    Can an AI agent really click its own “Approve” button?

    Yes, and vendors now say so plainly. The category has a name: computer-use agents (for example, Anthropic’s Claude Computer Use and OpenAI’s Operator, now folded into ChatGPT’s agent mode) act by reading a real screen and clicking on it the way a person would. In its November 2025 research on browser agents, Anthropic notes that these agents work by “navigating to URLs, filling forms, clicking buttons, downloading files,” and concludes that even after major robustness gains, “no browser agent is immune to prompt injection.” Their reported attack success rate dropped to around 1 percent, which they describe as still “meaningful risk,” not a solved problem.

    An approval button is just another button on the screen. If the agent can see and click the page, it can see and click the “Approve” on a consent dialog rendered in that same page. This stops being theoretical once you add prompt injection. Palo Alto Networks Unit 42 documented in March 2026 that indirect prompt injection, where hidden instructions are planted in web content the agent reads, is “no longer merely theoretical but is being actively weaponized,” with observed attacker goals including “unauthorized transactions” and “sensitive information leakage.” An injected instruction that says “approve the pending request” is executed the same way as any other instruction the agent picks up.

    Why isn’t a confirmation dialog enough?

    Because a click is weak evidence of a considered human decision, even when a real human is present. Anthropic reported that in Claude Code, users approved “roughly 93% of permission prompts,” and observed that “the more approvals a user sees, the less attention they pay to each.” That is approval fatigue in the best case, where a human is actually in the loop. In the worst case, where the agent controls the input path, there is no human in the loop at all, and the click carries no signal whatsoever.

    The lesson is that the security of a consent step does not come from the presence of an “Approve” button. It comes from where the button lives. If the decision surface sits inside the agent’s execution context, the agent can complete it, and the confirmation becomes ceremony rather than control.

    What does a real human-in-the-loop actually require?

    The approval has to be a ceremony the agent cannot complete from where it runs. In practice that means three properties:

    • The grant is authored by the person, not the agent. The user chooses the scopes and the duration inside the application’s own authenticated session, not through a redirect or dialog the agent set in motion.
    • The decision surface is outside the agent’s reach. If approving requires an action on a channel the agent does not control, an injected instruction has nothing to click.
    • Escalation always returns to the human. When an agent needs more access than it was granted, that request cannot be self-served. It has to route back through the same out-of-band decision the person made the first time.

    This is why “add a human approval step” is necessary but not sufficient. The approval step has to be one the agent physically cannot perform on its own, or it collapses back into the problem it was meant to solve.

    How does user-mediated authorization solve this?

    User-mediated authorization is built on exactly this separation. The person opens a “Connect Your AI Agent” flow inside the app’s own session and selects what the agent may do and for how long. The app generates a single-use, time-limited connection credential and delivers it to the person through a channel the person controls, never to an agent endpoint, webhook, or callback URL. The person then hands that credential to their agent out of band, and the agent exchanges it for a scoped, revocable access token.

    The point that matters here: there is no redirect, callback, or programmatic path an agent can drive to create or expand a grant. The authorization decision happens outside the agent’s execution context, so a malicious instruction injected into the agent has no button to click and no endpoint to call. If the agent later hits an operation outside its scope, it gets an insufficient_scope response, and the only way forward is a fresh, user-mediated grant. There is no self-service escalation path.

    One honest edge case remains: a computer-use agent running on the person’s own machine could try to drive that connection screen too. This is why the escalation ceremony itself can be hardened. The requirement is the important part: the confirmation must be something the agent cannot complete from where it runs, such as an approval on a separate device the agent does not control, or a user-verified assertion from an authenticator registered before the task began. AgentAdmit implements this with WebAuthn user verification, the standard behind passkeys: an app can require that any grant which elevates an existing user’s scopes be confirmed with a presence ceremony, and can apply the same requirement to consent-setting changes generally. Other mechanisms that satisfy the same property work just as well; what matters is that no approval surface reachable from the agent’s execution context counts as proof of a human decision.

    This is the same failure mode behind incidents like the GitHub MCP “toxic agent flow” reported in 2025, where a benign request plus a poisoned public issue led an agent to leak private repository data through its own over-broad token, and the zero-click Microsoft 365 Copilot prompt-injection flaw (CVE-2025-32711). In each case the agent had standing authority it could exercise without a human re-entering the loop. Moving the grant and every escalation out of the agent’s reach removes that standing authority by design.

    User-mediated authorization complements standards like OAuth and protocols like MCP. MCP tells an agent what it can do; the authorization layer decides whether it is allowed, and keeps that decision where the agent cannot reach it.

    Frequently asked questions

    Can prompt injection make an AI agent approve its own access?

    If the approval surface is reachable from the agent’s execution context, yes. Prompt injection is an instruction the agent reads and acts on, and clicking an on-screen “Approve” is an action a browser or computer-use agent can take. Unit 42 documented indirect prompt injection being weaponized in the wild in early 2026, including for unauthorized transactions. The defense is to place the approval on a channel the agent cannot operate.

    Can a computer-use agent approve its own consent prompt?

    Yes. Computer-use agents such as Claude Computer Use and OpenAI’s Operator act by reading a screen and clicking on it, so an approval dialog rendered where the agent runs is just another button it can press. A consent step shown on the same device the agent controls therefore proves nothing. The fix is to require approval on a channel the agent cannot operate, so the decision is made outside its reach.

    Is a human approval click enough to stop AI agent misuse?

    Not on its own. Anthropic found users approved about 93 percent of Claude Code permission prompts and grow less attentive as prompts pile up. A click confirms that something clicked, not that a human evaluated the specific action. A confirmation step is only as strong as the agent’s inability to complete it.

    How do you stop an AI agent from escalating its own permissions?

    Remove the programmatic path to more access, then harden the human path. With user-mediated authorization, a request beyond the granted scope returns an insufficient_scope error, and the only way forward is a new grant the person authors in the app’s own session. Because a computer-use agent on the person’s machine could try to drive that session too, the elevation ceremony can additionally require proof of human presence that the agent cannot produce from where it runs, for example WebAuthn with user verification from a pre-registered authenticator, or an approval on a separate device the agent does not control.

    Does this replace OAuth or MCP?

    No. It complements them. OAuth and MCP handle authentication and capability discovery. User-mediated authorization adds the piece they do not: a per-user, per-agent, scoped grant that the user controls and that lives outside the agent’s execution context.

    AgentAdmit is the authorization layer for AI agents, built so the authorization decision never sits where an agent can click it. Learn more at agentadmit.com.

    Related reading: What is user-mediated authorization for AI agents?, What is the Context Access Divide?, and MCP security: how to let an AI agent access user data safely, What is caller-identity consent for AI agents?.

  • What Is the Context Access Divide?

    Short answer: The Context Access Divide is the gap between AI users whose agents can retrieve relevant context from their own files and data automatically, and users who must find and attach the right documents by hand at every prompt. The term comes from a July 2026 arXiv preprint by Masahiro Fujita, a sociologist at Kansai University. The paper argues for broader access to open dynamic retrieval across ecosystems. We agree, with one addition the paper does not address: once an agent can reach your entire corpus on its own, the deciding question becomes who authorizes that reach, for what, and for how long. That is an authorization problem, and most deployments have not solved it.

    What does the Context Access Divide paper actually say?

    The paper (arXiv 2607.08495, submitted July 9, 2026, a preprint that has not been peer reviewed) extends earlier work on “agentic inequality,” which measured who can access AI agents and at what capability level. Fujita’s point is that two people on the same subscription tier, using the same model, can still get categorically different value from it. What separates them is a single architectural feature: whether the system retrieves context on its own or waits for the user to supply it.

    He sorts AI interfaces into three architectures. In the Manual Attachment Model, the user hunts down the relevant files and uploads them at each query. In what he calls Walled dynamic retrieval, the assistant fetches context autonomously but only inside one vendor’s ecosystem, the way Copilot reads your Microsoft 365 documents or Gemini reads your Google Drive. In Open dynamic retrieval, the agent can reach across ecosystems into local files, email, databases, and third-party services, which is what the Model Context Protocol (MCP) enables.

    The core argument is that manual attachment fails mathematically as your files accumulate. Drawing on memory research, the paper models how a person’s ability to recall which documents matter degrades as the corpus grows, so for a knowledge worker with twenty years of files, hand-feeding context is not an inconvenience. It is a ceiling on what AI can do for them. Fujita calls the divide a “macro-consequential micro-variable”: a per-interaction design detail whose effects add up to society-level inequality.

    What does the paper propose to do about it?

    Fujita’s recommendations are aimed at platforms and regulators: transparency about which retrieval architecture a product actually ships, interoperability mandates so platforms support open retrieval protocols, data portability so users can move their corpus without losing retrieval capability, and public procurement standards that favor open architectures. He also names a market dynamic worth remembering: vendors have every incentive to offer capable retrieval inside their walls, because it delivers the user experience while deepening lock-in. Nobody profits from building the open version, so the market under-supplies it.

    One thing the paper does not propose, despite how naturally it fits, is any mechanism for user control over what agents retrieve. Its governance instruments are about which architectures exist and who can access them, not about how a specific user authorizes a specific agent to touch a specific slice of their data.

    The question the paper leaves open: who authorizes the retrieval?

    Take the paper’s prescription seriously and picture the end state. Every knowledge worker has agents with standing, autonomous reach into their email, files, notes, calendars, and third-party accounts. The retrieval problem is solved. The trust problem has just become enormous.

    Agents process untrusted input, which means their access can be turned against their owner. In the GitHub MCP incident documented by Invariant Labs in May 2025, a poisoned public issue was enough to make an agent exfiltrate private repository data, using the same token its owner had legitimately configured. The agent did not malfunction. It did exactly what its access allowed, on instructions its owner never gave.

    Now look at how retrieval access is actually granted today. Astrix’s 2025 scan of MCP servers found that of those requiring credentials, 53 percent use static API keys or personal access tokens and only 8.5 percent use OAuth at all. The dominant setup behind “autonomous context retrieval” is a broad, long-lived credential in an environment variable that the user configured once and cannot see, limit, or revoke per agent. Expanding retrieval on top of that foundation does not close a divide. It scales an exposure.

    This is why we read the Context Access Divide as an authorization problem wearing an inequality costume. The paper is right that autonomous retrieval is the future of useful AI. It is also the reason per-agent, user-controlled authorization stops being optional.

    How user-mediated authorization makes open retrieval adoptable

    The failure mode in every incident above is the same: the credential lives in an automated channel the agent controls, so whatever manipulates the agent inherits the access. User-mediated authorization (the model AgentAdmit implements, patent pending) removes that channel. The user starts the connection inside the app that holds their data, chooses exactly which scopes to grant and for how long, and receives a single-use connection token themselves. The user hands that token to their agent; the app never delivers a credential to an agent endpoint, webhook, or callback. There is no automated path from “injected prompt” to “new access.”

    The result is retrieval an owner can reason about. Each agent holds a scoped, time-limited credential of its own. Every call is validated and logged. Revoking one agent takes one click and does not disturb the others. A read-only research agent can see read endpoints and nothing else. None of this restricts what the paper wants users to have. It is what makes granting that reach a sane decision, in the same way that MCP answers what an agent can do while authorization answers whether this agent, for this user, is allowed to. The approach complements standards like OAuth rather than replacing them; we have documented it in an Internet-Draft submitted to the IETF, draft-emerson-oauth-user-mediated-delivery (a work in progress).

    Fujita notes a “configuration gap”: platforms supporting MCP does not mean users experience dynamic retrieval, because setup demands technical sophistication. Authorization design is part of that gap. A consent flow a non-technical user can complete, inspect, and undo is not just safer. It is one of the things that lets the people on the wrong side of the divide actually cross it.

    Frequently asked questions

    Is the Context Access Divide paper peer reviewed?

    No. It is an arXiv preprint (cs.CY, July 2026) by a single author, Masahiro Fujita of Kansai University. That does not make it wrong, but cite it as a preprint, not as settled research.

    What is the difference between walled and open dynamic retrieval?

    Walled retrieval fetches context autonomously but only within one vendor’s ecosystem, like an assistant that reads your documents inside a single office suite. Open retrieval crosses ecosystem boundaries over open protocols such as MCP, reaching local files, email, and third-party services. The paper argues only the open form serves users whose data lives in many places.

    Doesn’t MCP already handle authorization?

    MCP specifies authentication for connections, and its 2025-2026 revisions strengthened it. What it does not give you on its own is per-user, per-agent, scoped consent that the data owner controls and can revoke. Authorization is the layer that decides what an authenticated agent is allowed to touch.

    Does closing the divide mean giving agents unrestricted access to my data?

    No, and it should not. The useful end state is agents with exactly the reach their owner granted: scoped to the task, time-limited, revocable in one step, and logged. Autonomous retrieval and tight authorization are not in tension. The second is what makes the first safe to adopt.

    AgentAdmit is the authorization layer for AI agents: user-mediated, scoped, revocable access to the apps that hold your users’ data. See how it works at agentadmit.com.

  • What Is Discovery-by-Introspection for AI Agents?

    Short answer: Discovery-by-introspection is a mechanism that tells an AI agent what it is allowed to do at the moment its credential is checked. When the agent exchanges or validates its token, the response comes back with an operational map: the endpoints its scope permits, and for each one that takes input, the exact fields, types, and which are required. The map is filtered to the agent’s granted scope, so a read-only agent is never even shown a write operation. The agent arrives knowing nothing about the app and is fully operational from that one response, with no documentation and no manual integration.

    Watch: discovery-by-introspection in 37 seconds

    The Lit Path, a 37-second film on discovery-by-introspection from AgentAdmit.

    Transcript: Without a map, an agent guesses. And guessing breaks things. Discovery by introspection answers at the exact moment the credential is checked. Back comes an operational map: only the doors its scope permits, and the exact shape of each one. A read-only agent is never even shown a write operation. What it cannot touch does not exist. The agent arrives knowing nothing, and leaves fully operational. AgentAdmit.

    The problem it solves

    Connecting an agent to an app normally means someone reads the API documentation and builds an integration: base URLs, endpoint lists, field names, request formats. That work is slow, it breaks when the API changes, and it does nothing for authorization. Worse, discovery and permission are usually separate systems, so an agent can often see far more of an API than it is allowed to use, and what it can use is documented for humans, not for software that has to construct valid requests on its own.

    Without structural information, an agent guesses. It sends a field named “project_title” when the endpoint expects “name,” gets a validation error, and retries. Multiply that across every endpoint and every app, and agent integrations become brittle exactly where they need to be dependable.

    How discovery-by-introspection works

    The mechanism runs at the same moment the agent’s credential is validated, in either of two ways: during the initial token exchange, or later, when an agent with an existing token asks the introspection endpoint to refresh its view. That refresh works only while the user’s grant is still alive. The user sets how long access lasts when they approve the connection, anything from an hour to thirty days to until-I-revoke, depending on what the app offers, and once the grant expires or the user revokes it, there is nothing left to introspect. The agent has no way to renew access on its own; getting back in takes a fresh grant from the user. Either way, the sequence is the same.

    1. The agent presents its credential. No prior knowledge of the app is required.
    2. The system identifies the app and the agent’s granted scopes from the credential.
    3. The full capability map is filtered down to the agent’s scope. Operations that require permissions the agent was not granted are removed, not grayed out. Two agents connected to the same app with different scopes receive different maps.
    4. Field-level schemas are attached. Every authorized operation that accepts input comes with its required fields, optional fields, data types, and descriptions.
    5. One response returns everything: the app’s identity, where to send requests, and the filtered, schema-complete operation map.

    The response is execution-enabling rather than descriptive. It is not documentation for a person to read; it is structure an agent can act on directly, and it stays valid whether the agent calls the operations over HTTP or registers them as tools in a tool-use framework.

    Why filtering by scope matters for security

    Least privilege usually stops at enforcement: the agent is blocked if it tries something out of scope. Discovery-by-introspection moves least privilege up into visibility. An agent granted read-only access receives a map containing only read operations, so the write surface of the API is not merely forbidden, it is invisible. An agent cannot be steered toward operations it has never been told exist, which shrinks what a compromised or manipulated agent can even attempt. And because the map is regenerated from the live grant, revoking or narrowing a scope changes what the agent sees, not just what it is permitted.

    When an agent genuinely needs something outside its grant, there is a path, and it runs through the user. The denied request comes back naming the specific permission that was missing, so the agent can tell the user exactly what it needs and why. Granting it is a step-up: the user approves the additional scope through the same authorization flow they used the first time, or declines. There is no API through which an agent can expand its own permissions, so scope escalation always requires a conscious human decision.

    How this relates to the self-describing credential

    They are two halves of one connection story. The self-describing credential gets the agent to the door: the token itself tells the agent where to exchange it. Discovery-by-introspection is what the agent receives once inside: the scope-filtered, schema-complete map of what it may do. Together they take an agent from “holding a token” to “making correct, in-scope API calls” in a single exchange, with the user’s grant deciding both access and visibility. Both begin with user-mediated authorization: the user approves the scope, and everything the agent sees downstream flows from that choice.

    Frequently asked questions

    Is discovery-by-introspection the same as API documentation or an OpenAPI spec?

    No. Documentation describes the whole API for human developers, regardless of who is asking. Discovery-by-introspection returns a per-agent view at credential-check time: only the operations that agent’s scope allows, with field-level schemas attached, in a format the agent can execute against directly.

    When does the agent receive the discovery response?

    Either during the initial token exchange, so a single request returns both the access token and the full operational map, or later from an introspection endpoint, so an agent with an existing token can refresh its view of what it is allowed to do without repeating authorization. The refresh only works while the user’s grant is still active: if access has expired or been revoked, the agent gets nothing, and only the user can grant access again.

    What does scope filtering actually change?

    It changes what the agent can see, not just what it can do. Operations outside the agent’s grant are absent from the response entirely, so a read-only agent never learns the write endpoints exist. Enforcement still checks every call, but the attack surface an agent can be pointed at is smaller from the start.

    What happens when the agent needs a permission it was not granted?

    The request is denied with a response naming the specific missing permission, so the agent can tell the user exactly what it needs. The user then approves the additional scope through the same authorization flow, or declines. This step-up always goes through the user; there is no API through which an agent can expand its own permissions.

    Does it work with tool-use frameworks like MCP?

    Yes. The discovered operations carry enough structure to be registered as tools in an agent’s tool-use framework, and the map is independent of transport, so it holds whether the agent calls operations over HTTP or through a tool interface.

    Discovery-by-introspection is one of the inventions behind AgentAdmit, and it is patent pending.

    AgentAdmit is the authorization layer for the agent economy: user-mediated, scoped authorization for AI agents, where one exchange returns the token and the scope-filtered map of everything the agent may do. Scoped. Revocable. Auditable. See how AgentAdmit works.

    Related reading: how to let an AI agent access a user’s account safely and MCP security: how to let an AI agent access user data safely.


  • What Is a Self-Describing Credential for AI Agents?

    Short answer: A self-describing credential is a token that carries everything an AI agent needs to connect, so the agent can start working without separate documentation or configuration. The agent reads the exchange location out of the token itself, exchanges it once, and gets back its access token plus the scopes it was granted, the endpoints it can call, and the request schemas for each one. It turns “here is a token” into “the agent is operational” in a single step, with no shared secrets and no manual setup.

    Watch: what a self-describing credential is in 37 seconds

    “The Map Inside” a 37-second film on self-describing credentials for AI agents, from AgentAdmit.

    Transcript: An API key is a bare secret. It says nothing, and it unlocks too much. A self-describing credential puts the map inside the token. The agent reads where to exchange it from the token itself. No documentation. No setup. One exchange returns its scopes, its endpoints, and the exact shape of every call it may make. From here is a token to fully operational, in one step. AgentAdmit.

    Why connecting an AI agent to an app is usually painful

    The normal way an agent gets access to an app is a scavenger hunt. Someone reads the API docs, finds the base URL, configures endpoints, wires up an auth flow, and pastes in a key. Every new integration repeats the work, and every step is a chance to over-grant access or leak a secret. The agent ends up holding a broad credential and a hand-built map of what to do with it.

    A self-describing credential removes that work by putting the map inside the token.

    How a self-describing credential works

    Two things make the token self-describing.

    • The agent finds the exchange point on its own. The location where the token is redeemed is encoded in the token itself, so the agent determines where to exchange it without external instructions, documentation, or a separate discovery service.
    • One exchange returns everything. When the agent exchanges the token, it receives its scoped access token along with operational instructions in the same response: which app it is talking to, where to send requests, the specific endpoints its scope allows, and the field-level request schema for each of those endpoints.

    The result is that an agent goes from holding a credential to making correct, in-scope calls without a human writing integration code for it.

    What a self-describing credential gives you that an API key does not

    An API key is a bare secret. It says nothing about who granted it, what it is for, or what the agent may do with it, and it usually unlocks far more than the task at hand. A self-describing credential is the opposite on every count:

    • Zero configuration. No docs, no endpoint list to maintain, no shared setup between your app and the agent.
    • Least privilege by construction. The endpoint map the agent receives is filtered to the scope the user approved. A read-only agent is only ever shown read endpoints, so it cannot discover or call anything beyond its grant.
    • No shared secrets to leak. The agent does not need pre-shared configuration or credentials to learn how to operate, because the token carries what it needs.

    Does a self-describing credential work with any AI agent?

    It works directly with any agent that can make HTTP requests, such as Claude Code, Codex, or a custom agent, because those agents can read the token and call the exchange endpoint themselves. Chat interfaces that cannot make arbitrary calls, like Claude Desktop or ChatGPT, connect through an MCP server that acts as the bridge. Either way the agent gets a token it can act on immediately.

    Where this fits with user-mediated authorization

    A self-describing credential is how the agent operates. User-mediated authorization is how the agent got the credential in the first place: the user approved a scope and the token was delivered to the user, not pushed to the agent through an automated channel. Together they mean the user decides what an agent may do, and the agent can then do exactly that, and nothing more, without a manual integration. For the granting side, see what user-mediated authorization for AI agents means.

    Frequently asked questions

    Is a self-describing credential the same as an API key?

    No. An API key is a bare secret with no built-in meaning, usually granting broad access. A self-describing credential tells the agent where to exchange it and, after exchange, returns the scopes, endpoints, and request schemas the agent is allowed to use, so it operates in-scope without extra configuration.

    How does the agent know where to send the token?

    The exchange location is encoded in the token itself. The agent reads it directly from the credential and sends its exchange request there, with no external documentation or separate discovery step.

    What does the agent get back when it exchanges the token?

    A scoped access token plus operational instructions in one response: the app it is connecting to, where to send requests, the endpoints permitted by its scope, and the field-level request schema for each. That is enough for the agent to start making correct calls immediately.

    Does the token expose every endpoint in the app?

    No. The endpoint map is filtered to the scope the user approved. An agent granted read access is only shown read endpoints, so a self-describing credential stays least-privilege rather than handing over the whole surface of the app.

    The self-describing credential is one of the inventions behind AgentAdmit, and it is patent pending.

    AgentAdmit is the authorization layer for the agent economy: user-mediated, scoped authorization for AI agents, with a patent-pending self-describing token that makes an agent operational in one exchange. Scoped. Revocable. Auditable. See how AgentAdmit works.

    Related reading: how to let an AI agent access a user’s account safely and MCP security: how to let an AI agent access user data safely.

  • MCP Security: How to Let an AI Agent Access User Data Safely

    Short answer: MCP standardizes how an AI agent discovers and calls your tools and data, and it added an OAuth-based authorization framework to go with it. What it does not give you on its own is per-agent, scoped, revocable access that the end user controls. To let an agent access user data safely through MCP, add a layer of user-mediated authorization: the user approves specific scopes, the credential is delivered to the user rather than pushed to the agent through an automated channel, and every call is checked against that grant. MCP handles what the agent can see. User-mediated authorization handles whether it is allowed.

    What MCP handles, and what it leaves to you

    The Model Context Protocol solved a real problem: a common way for agents to find tools, read resources, and call them across different systems. Its authorization spec is OAuth-based and is getting stricter. The protocol’s 2026-07-28 revision hardens authorization with six changes, including issuer validation per RFC 9207 and cleaner dynamic client registration.

    But a protocol that standardizes authentication and transport does not, by itself, answer the question a data owner actually cares about: which specific agent is allowed to do which specific thing with this user’s account, and can the user see it and take it back. That is authorization at the level of the individual user and the individual agent, and it is the part builders keep having to solve themselves.

    The authorization gaps builders keep hitting

    Three problems show up again and again when agents get access through MCP.

    Static, over-broad credentials. An audit of more than 5,200 MCP servers found only 8.5% use OAuth. The majority rely on static API keys or personal access tokens, and most pass them through environment variables. A long-lived key in an env var is broad by default and rarely scoped to the one task at hand.

    The confused deputy. The MCP spec itself warns about it: when a server sits in the middle as an OAuth proxy and does not properly validate consent per client, an attacker can get access to a downstream API as the user without the user’s explicit approval. The spec’s own guidance is that proxy servers must implement per-client consent. The trouble is that this is left to each implementation to get right.

    Injected instructions turning access into exfiltration. Agents read untrusted content, and that content can carry commands. Invariant Labs showed a “toxic agent flow” where a malicious public GitHub issue steered an assistant into exposing private repositories through access it already held. EchoLeak (CVE-2025-32711) showed a single crafted email making Microsoft 365 Copilot leak internal data with no click. In each case the credential was valid. What failed was scoping and control over how that credential could be used.

    How to close the gap: user-mediated authorization on top of MCP

    User-mediated authorization is a model where the account holder grants the agent access directly, and the resulting credential is delivered to the user rather than pushed to the agent through an automated channel. The user hands it to their agent. There is no redirect, no callback, and no automated path between your app and the agent for a prompt injection or a misconfiguration to intercept.

    In practice that means:

    1. The user approves specific scopes in your app’s own UI, in plain language, in their authenticated session.
    2. The credential goes to the user, not the agent. The authorization decision happens outside the agent’s execution context, so an injected instruction has nothing to hijack.
    3. Access is scoped, time-limited, and revocable per agent. The user can pull one agent’s connection without breaking the others.
    4. Every call is checked against the grant, and each grant is recorded, so you can answer who authorized this agent and for what.

    This does not replace MCP. It sits on top of it. MCP tells the agent what it can do. User-mediated authorization decides whether it is allowed, on every call, under the user’s control.

    How it fits with the MCP spec

    MCP’s tightening authorization rules and user-mediated authorization are complementary. The spec’s hardening makes the OAuth plumbing safer between clients and servers. User-mediated authorization adds the piece the plumbing does not cover: end-user, per-agent, scoped consent that the user owns and can revoke. For an MCP server, the addition is small. Carry a user-approved token and verify it, per call, against the scopes the user granted. The agent gets a token it can use immediately, and the user keeps a dashboard of exactly which agents can do what.

    Frequently asked questions

    Does MCP handle authorization on its own?

    MCP provides an OAuth-based authorization framework and is hardening it, which covers authentication and the client-to-server flow. It does not, by itself, give end users per-agent, scoped, revocable control over what a specific agent can do with their account. That user-level authorization is the layer you add on top.

    Is an MCP server secure by default?

    No. Security depends on how it is implemented. Audits show most MCP servers rely on static API keys rather than OAuth, and the MCP spec itself warns that proxy servers must implement per-client consent to avoid confused-deputy attacks. A safe deployment scopes access to specific actions, delivers the credential to the user, and checks every call against what the user approved.

    What is a confused deputy attack in MCP?

    It happens when a server in the middle holds a user’s authorization and passes it downstream without properly checking, per client, that this particular agent was approved for it. The attacker never steals the credential directly; they get the intermediary to use its authority on their behalf. Per-client consent and validating authorization on every call are the defenses.

    Does adding user-mediated authorization slow the agent down?

    Approval happens once per grant, when the user allows it. After that the agent operates within its scope without re-prompting, and a self-describing token lets it start working without extra setup. The user gets control and an audit trail without turning every action into a permission dialog.

    User-mediated delivery is one of the inventions behind AgentAdmit, and it is patent pending.

    AgentAdmit is the authorization layer for the agent economy: user-mediated, scoped authorization for AI agents that complements MCP. The credential is delivered to the user, not an automated channel. Scoped. Revocable. Auditable. See how AgentAdmit works.

    Related reading: What is user-mediated authorization for AI agents? and how to let an AI agent access a user’s account safely.

  • What Is User-Mediated Authorization for AI Agents?

    Short answer: User-mediated authorization is a model where the account holder grants an AI agent access directly, and the resulting credential is delivered to the user rather than pushed to the agent through an automated channel. The user gives the credential to their agent, so there is no redirect, callback, or automated path between the app and the agent for an attacker to intercept. Access is scoped to specific actions, time-limited, and revocable. It is how you answer the question every platform now faces as agents multiply: under whose authority is this agent acting?

    Watch: user-mediated authorization in 33 seconds

    The Human Decides, a 33-second film on user-mediated authorization from AgentAdmit.

    Transcript: Every AI agent wants access to your apps. Today, credentials travel through channels no human ever sees. User-mediated authorization changes the path. The credential is delivered to the person. The human hands the agent exactly the access they choose. Nothing more. AgentAdmit. The human decides.

    Why AI agents need a different authorization model

    Traditional access was built for two things: a person logging in, or one server calling another with a shared key. An AI agent is neither. It acts on a user’s behalf, often continuously, often across several services at once, and it decides in the moment which calls to make. That breaks the old assumptions in two ways:

    • The credential travels an automated channel. Most agent auth today leans on API keys, OAuth redirects, or environment variables. These move a credential with no human at the point of delivery, so they can be intercepted through prompt injection or misconfiguration.
    • The access is broad and hard to undo. Agents are often handed long-lived tokens that grant far more than the task needs, with no clean way to scope a single agent, expire its access, or revoke it on its own.

    The industry has started naming what goes wrong. Security teams call the accountability problem the attribution gap: the distance between what an agent did and your ability to prove who authorized it. When a credential rides an automated channel and grants broad access, an injected instruction can turn the agent into the attacker, and afterward no one can cleanly say who approved what. A model built for AI agents has to close both halves: the interception risk and the attribution gap.

    How user-mediated authorization works

    Four things keep the human in control at the moment access is granted.

    • The user grants access directly. Approval happens with the account holder, in plain language, for specific scopes. The developer does not stand in the middle holding the keys.
    • The credential is delivered to the user. It goes to the human, who gives it to their agent. There is no redirect, no callback, and no automated path between the app and the agent. This is the piece most systems skip, and it is what keeps the user as the authority.
    • The token is self-describing. The agent extracts where to exchange it from the token itself, and after exchange it receives its scopes, endpoints, and request schemas, so it can start operating without extra configuration or shared secrets.
    • Access is scoped, time-limited, and revocable. The user chooses what each agent can do and for how long, and can revoke one agent’s connection at any time without affecting others.

    How is this different from API keys or a normal consent screen?

    An API key or service account is a single broad secret that moves through an automated channel. It cannot express who approved it, it usually grants far more than one task needs, and revoking it tends to break everything else that shares it. A standard consent screen is better, but on its own it still typically returns the credential through an automated redirect or callback and hands the agent broad access.

    User-mediated authorization changes two things. The credential is delivered to the user instead of flowing to the agent automatically, and access is scoped per agent, time-limited, and revocable. The result is least-privilege access that is provable after the fact, not a broad secret you hope never leaks.

    Why deliver the credential to the user instead of the developer?

    Because that is what keeps the user as the authority. If the developer holds the credential, the user is trusting the developer’s infrastructure with their account. Delivering it to the user means a developer never has to custody raw credentials, and a breach of the developer’s systems does not expose user accounts.

    For a step-by-step version aimed at builders, see how to let an AI agent access a user’s account safely.

    Frequently asked questions

    Is user-mediated authorization the same as a standard login or authorization flow?

    No. It complements standards like OAuth rather than replacing them. It changes how the credential reaches the agent, through the user instead of an automated redirect or callback, and adds per-agent scoping, expiry, and revocation, so the human approves and controls access at the moment it is granted.

    Why not just push the credential straight to the agent?

    Because an automated path between your app and the agent is exactly what a prompt injection or a misconfiguration can intercept. Delivering the credential to the user removes that channel. The user gives it to their agent, so there is no automated hop for an attacker to sit on.

    Does this slow the agent down?

    Authorization happens once per grant, when the user approves it. After that the agent operates within the scope it was given without re-prompting, and a self-describing token means it does not need extra setup to start working. The user gets control and an audit trail without turning every action into a permission dialog.

    What is the simplest first step toward this model?

    Stop moving raw, broad credentials to agents through automated channels. Deliver scoped access that the user approves, make each connection time-limited and revocable on its own, and keep a record of every grant.

    User-mediated authorization with credential delivery to the user is the core invention behind AgentAdmit, and it is patent pending. We have also written the model up for the standards community: you can read our Internet-Draft submitted to the IETF OAuth community (a work in progress, not an adopted standard).

    AgentAdmit is the authorization layer for the agent economy: user-mediated, scoped authorization for AI agents. The credential is delivered to the user, not an automated channel. Scoped. Revocable. Auditable. See how AgentAdmit works.