Whose Leak Is It? DLP When an AI Agent Holds Your OAuth Token
$ grep -n "^##" 2026-06-whose-leak-dlp-ai-agent-oauth-scope.md
I keep four or five Claude agents running across my projects, and a couple are wired straight into the business systems I actually use — Xero for the books, HubSpot for the pipeline — over my own OAuth token. The day I connected the first one, I sat at the consent screen and made the call every operator makes: which scopes to grant. The official Xero connector will ask for the lot if you let it, payroll among them, so I trimmed the grant to the handful an accounts agent could actually use.
Here is what I told myself while I did it, because it felt obviously true: the agent calls the same API my browser would, with my token, so it can only ever see what I can see. The boundary is the vendor's — Xero defines it, Xero enforces it — so data loss prevention is Xero's problem, not mine. I'd done the responsible thing and the rest was somebody else's RBAC.
The vendor enforces the token's API access, which need not match my browser permissions. But that answers only one question — who is allowed to read this data? — and skips another: given that the agent can read it, where is it allowed to go next?
The question I'd actually answered
That second question is a data loss prevention problem. Proofpoint defines DLP as the policies and processes that "identify and prohibit unauthorized exposure, sharing, or transfer of sensitive data" (Proofpoint). Exposure, sharing, transfer — every word is about what leaves. A browser session blurred reading and acting into one human act; an agent splits them. It reads — access, the vendor's domain, working as designed — and then it can transmit onward through a tool call, an outbound request, a created record. That second capability is egress, and it lives downstream of the token, across boundaries a source system's access check alone does not govern.
There's a sharper twist, from a vendor's own documentation. HubSpot's OAuth quickstart for legacy public apps explains that a contacts-read token can reach every contact in an account even when the authorizing user's UI access covers only their own contacts (HubSpot docs). So even my comfortable premise — "it can only see what I can see" — isn't reliably true: API access depends on the provider and app type, not just my browser permissions. Neither the scope nor the browser permissions settle which onward transfers are appropriate.
The heist that broke nothing
In May 2025, Invariant Labs published an attack against the official GitHub MCP server, and it maps onto my setup uncomfortably well: a developer's own personal access token, an official MCP server, an AI assistant doing ordinary work. The token reaches both a public repo and a private one — normal. An attacker buries a prompt-injection payload in a public-repo issue. Later the developer asks their assistant to look at the open issues; the agent loads the malicious one into context, the planted instructions take over, and — using the same legitimate token — it reads files from the private repo and exfiltrates them by opening a pull request to the public one, where anyone can now read them. Invariant's researchers walked away with real specifics about their test user: private repository names, a plan to relocate to South America, even a salary (Invariant Labs).
No token stolen, no tool poisoned, no authentication broken. Every call authorised. And the line that should be pinned above every agent deployment is theirs:
"This is not a flaw in the GitHub MCP server code itself, but rather a fundamental architectural issue that must be addressed at the agent system level. This means that GitHub alone cannot resolve this vulnerability through server-side patches."
EchoLeak exposed another route through Microsoft 365 Copilot: a crafted email could induce it to disclose internal data. Microsoft fixed that vulnerability. The shared lesson is narrower than “nothing can be patched”: permission to retrieve data does not establish permission to disclose it to a different audience.
What a patch can close
Simon Willison called the dangerous combination the lethal trifecta in June 2025: private data, untrusted content, and external communication. His verdict is blunt: combine the three and "an attacker can easily trick it" into sending your data out, and mitigations only lower the odds rather than remove them. My Xero agent combines all three — private financial data, invoice PDFs or supplier emails, and outbound calls. Which controls block a given route is an engineering question; that a route exists is not.
The MCP authorization specification requires audience validation and forbids token passthrough. Those controls address specific authorization failures. They do not decide whether an otherwise permitted tool call should carry invoice data to a particular recipient. EchoLeak's fix shows that vendors can close concrete attack paths; the wider risk still needs controls across the agent and its connected systems.
The split
Think about a contractor with a building pass for third-floor work that also, because the policy was drawn broad, opens the records room on two. He photographs an open filing cabinet and walks out. No alarm: the pass was legitimate, his presence authorised, and nothing at the door was watching what left in his pocket. Access checks and controls on onward disclosure both matter. Their owners may overlap.
The source vendor enforces access. Honour the scopes, validate the token audience, and — the part that's actively improving — ship granular scopes so the pass opens fewer rooms. Xero is mid-migration: as of March 2026 newly created apps must use granular scopes, with broad legacy ones deprecated. Its developer blog frames the rationale — "instead of broad access, your app now requests only the exact permissions it needs." That narrows what a token can reach; it doesn't settle every responsibility downstream.
The operator must configure the whole workflow. The half my original model skipped, and it starts with the one lever I fully control: least-privilege token issuance. The official Xero MCP server's bearer-token scope list is broad — roughly twenty distinct scope strings spanning invoices, payments, bank transactions, reports, contacts, settings, and payroll (payroll.settings, payroll.employees, payroll.timesheets). The README's own Claude Desktop example narrows it to three: accounting.invoices accounting.contacts accounting.settings (XeroAPI/xero-mcp-server). Twenty versus three. An agent that reconciles invoices has no business holding a token that can read employee payroll, and the difference is one environment variable I set. OWASP recommends executing actions "in the context of that specific user, and with the minimum privileges necessary" (OWASP).
Scope minimisation reduces what an attacker could extract. Egress controls can block particular routes: remove unnecessary send tools, constrain destinations, and require review of consequential writes and sends. OWASP recommends enforcing authorization in downstream systems, rather than asking the model to police itself, alongside monitoring and rate limits (Excessive Agency). A destination allowlist alone is insufficient if the agent can publish private data into a public record on an allowed service. The policy needs to cover the action, data and recipient too.
Accountability follows the role
For personal data, delegating processing does not erase the organisation's duties. Under GDPR, Articles 5(2) and 24 require controllers to demonstrate compliance; Article 28 governs their use of processors. Processors also have obligations, and Article 82 permits liability for damage caused by breaches of processor-specific duties or actions outside lawful instructions. A vendor is not absolved merely because its API accepted a valid token (GDPR).
Singapore's PDPA section 4(3) likewise keeps an organisation responsible for personal data processed on its behalf and for its purposes by a data intermediary. Section 4(2) retains direct intermediary duties, including protection under section 24. A service provider processing on another organisation's behalf may be a data intermediary; the AI software itself is not (PDPA, sections 2 and 4).
None of that automatically assigns liability to whoever clicks the OAuth consent screen; the PDPA even excludes employees acting in the course of employment from those organisational obligations under section 4(1)(b). But in my setup there is no employer to point at. I am the organisation, the token is mine, and the agent processes on my behalf and for my purposes. Whatever the vendor's duties, the obligation to know where the data goes next does not leave my desk. So my practical job is to establish who controls each boundary and what evidence shows the controls work, rather than treating a successful OAuth grant as the end of the discussion.
I can't infer the agent's API access from my browser permissions. And even a correctly scoped agent has an exit I'd never once had to think about.
$ subscribe --newsletter
Practical AI engineering, in your inbox
Field notes for technical leaders building agents, evaluation systems, governance, and production infrastructure.
Related
Giving an Agent an Inbox Without Giving It Your Mailbox
A dedicated email address limits which messages reach an agent; the harder details are untrusted content, sending authority and missing attachments.
The 30 Principles for Agentic Engineering — Part 4: Governance and Safety
Principles 21–25. The governance and safety layer: strictKnownMarketplaces, no goal-conflict prompts, quarterly AppSec, four telemetry signals, monthly incident discipline.
AI Reviews AI Is Not a Review: The Trust Trap Regulators Won't Accept
AI-reviews-AI looks like a control. Under MAS, the EU AI Act, and any reasonable audit, it isn't. Here's why your compliance team won't accept it — and the compensating controls that actually work.