A platform ships forty connectors. Each one is a small server behind a documented tool surface: a name, a description, a JSON Schema for its arguments, an OAuth client, and a credential that lets it reach the system it fronts. Each one went through review. Security looked at the transport and the token handling. A staff engineer read the tool descriptions and pushed back on two of them for being vague. Someone from the data team confirmed the service account was not the one with the admin grant. Legal glanced at the third-party terms. The connector shipped with a scope list, a changelog entry and a documentation page, and every one of those forty reviews reached a defensible conclusion about the thing in front of it.
Then a customer builds an agent and enables nine.
This whole section is a constructed illustration — the forty connectors and their reviews above, the nine enabled below, and everything in between. It is not a client engagement, not a disclosed incident, and not a description of any named platform's catalogue; the reviewers, the pushback and the enabled set are invented. I have built it out of mechanisms that are documented in the protocol specification and in published security research, because the argument needs a concrete trace and I will not manufacture one out of somebody's outage.
The nine are unremarkable: directory, mail, files, a configuration store, the transactional database, ticketing, an outbound HTTP fetch, the CI system, and internal search. The agent's job is to close yesterday's payment exceptions — pull the failed settlements from the previous day for one merchant, work out which are retryable, open tickets for the ones that are not, and post a summary. A product manager could describe that job in two sentences. It is a narrow, specific, entirely reasonable piece of work.
Now trace what the agent can reach, rather than what it was asked to do.
The database connector authenticates with a role. The role attaches to a schema, and the schema is not one merchant's failed settlements from one day — it is the settlements schema, which is every merchant, every day held online, plus the ledger views, plus whatever stored procedures the role is permitted to execute. Nobody granted that. The review approved a connector for the settlements database, and the settlements database is what it got.
The configuration connector reads a namespace. The namespace is where the platform keeps the values the services need at boot, which in every estate I have ever seen includes at least one connection string, at least one API key that predates the current secrets policy, and a webhook URL with a token baked into the path. The review approved a read-only connector for configuration, and read-only is exactly what it is. That was never the question.
The outbound fetch connector makes an HTTP request to a URL. It is the most obviously general thing in the set and also the one nobody argues about, because a connector that could only reach a fixed allowlist would be useless to most of the customers who want a fetch tool at all. The review approved it, noted the SSRF guard, and moved on.
Each of those three is fine. Held together, they are a path: read a namespace that contains credential material, and then post it somewhere. Nobody granted that path. Nobody reviewed it, because there was no review step whose input was the set. Two people granted two reasonable things at two different times, and a third party — a customer administrator with a checkbox interface — put them in the same process.
That distinction is the whole essay, so it is worth stating in the flattest possible terms. The reachable set of an enabled toolbelt is not the union of the reviewed scopes. The union is what the review process implies. The closure is what runs. The union is a sum over nine items and it is computable by reading nine documents. The closure is a fixed point over nine credentials and it is computable only by someone holding all nine at once — which, in the shipping architecture of every connector catalogue I am aware of, is nobody.
The objection that has to be answered before anything else
The strongest response to everything above is that observability already covers it, and this response deserves to be taken at full strength rather than waved at, because in my experience it is usually correct and the people making it are usually right about their own systems.
Platform observability at a large cloud or SaaS provider is genuinely, expensively good. There is a trace for the request. There is a data-plane access log for the query, with the principal, the resource, the timestamp and frequently the row count. There is an audit trail on the credential issuance and another on the credential use. There are anomaly detectors on egress volume, on unusual principal-resource pairs, on first-time-seen destinations. There are retention policies measured in years, a query engine over the whole of it, and an on-call rotation that is actually paged when the detectors fire. Several of these companies have shipped reachability analysis for their own identity systems — tooling that takes a policy graph and answers which principals can reach which resources under which conditions, statically, before anything runs. That is not a naive discipline. It is one of the most mature parts of the industry.
So the honest concessions first, all three of them. If the constructed path above were exercised, a trace would exist. If someone went looking afterwards, they could reconstruct it. And in a meaningful fraction of cases the egress detector would fire before the reconstruction was needed, because posting credential material to a new destination is exactly the shape those detectors are tuned for. Telling a principal engineer at a hyperscaler that their logging is inadequate is both insulting and, as a description of their logging, wrong.
The argument is not that the logging is inadequate. The argument is that logging answers a different question, and three properties of the gap make that precise.
A log entry is per-call; the finding is per-set. Every call in the constructed chain is individually well-formed. Reading a configuration namespace is what the configuration connector is for. Making an outbound request is what the fetch connector is for. There is no anomalous call to detect, because the anomaly is not in any call — it is in the adjacency of two of them, and adjacency is a property of the set that was enabled, not of any event in the stream. You can build a detector for the pair, and some teams have. But you have to know which pair, which means you have to have already computed the composition, which is the step this essay says is missing. The detector is downstream of the analysis, not a substitute for it.
The reachable set is counterfactual; logs are actual. The authority question is what may happen, and a log by construction contains only what did. The overwhelming majority of an agent's reachable set is never exercised in any given run, and the paths that matter for a review are precisely the ones that have not been taken yet. Asking the log about them is asking a record of the past to describe a space of possibilities. This is why reachability analysers exist for identity policy at all: the industry already accepted, for IAM, that logs do not answer reachability. The tool layer simply never got the equivalent object.
Detection is a control on the tail; this is a statement about the distribution. Grant excellent detection. What you are then detecting, repeatedly, across customers, is the default behaviour of your own product. Every fire is a customer who assembled a reachable set nobody computed for them, using a catalogue whose only unit of grant was a connector. A control that works is not the same as a design that is right, and the difference shows up as a permanent operational tax that scales with adoption rather than a defect that gets closed.
There is a fourth thing worth saying about the reachability analysers specifically, because they are the most serious version of the objection. They are excellent and they analyse the wrong graph. An IAM reachability analyser takes principals, policies and resources and computes what can reach what. A tool catalogue sits above that: the agent's principal is the connector's service identity, so from IAM's point of view there is one principal doing what it is entitled to do. The composition happens in the layer above the policy graph, in a runtime that decides which tool to call next based on the output of the last one, and the analyser has no representation of that layer at all. It is not that the analysis is wrong. It is that the object it analyses stops one level below where the interesting thing happens.
A second objection is quieter and more consequential, and I will take it up properly at the end: that this is the customer's configuration problem rather than the platform's product problem. It is the objection with the most institutional weight behind it and the least architectural support.
A name is not a bound
The physical fact underneath all of this is small enough to state in one line and load-bearing enough to spend a section on. A tool grant is written as a name and exercised as a transitive closure.
Take the specification at its word about what a tool actually is. In the Model Context Protocol specification of 18 June 2025, a tool definition consists of a name, a title, a description, an inputSchema which is a JSON Schema for the parameters, an optional outputSchema, and optional annotations. That is the entire list the specification's own Data Types section gives — the wire schema adds only a protocol-level _meta bag alongside it. Read the list looking for the field that constrains which rows, tables, endpoints, accounts or objects the tool may reach when it is invoked, and there is not one. The inputSchema types the arguments. It does not type the reachable resource set, and no other field does either.
This is not an omission in the protocol so much as an accurate reflection of where the information lives. The reachable set is a property of the credential the server holds, and the server obtained that credential from an authorization flow that knew nothing about the task. Which brings the second half of the fact into view.
The protocol's authorization specification is careful, modern and normatively strict. It requires OAuth 2.1, PKCE, dynamic client registration under RFC 7591, authorization server metadata under RFC 8414, protected resource metadata under RFC 9728, and resource indicators under RFC 8707. On resource indicators it is emphatic: clients MUST include the resource parameter in both authorization and token requests, identifying the server by canonical URI, and MUST send it regardless of whether the authorization server supports it; servers MUST validate that tokens presented to them were issued specifically for them as the intended audience. That is a real control and it is the right one for the threat it addresses.
It binds the token to a resource server. It does not bind the token to a task. And the specification is candid about the consequence in its own vocabulary: it defines no scope vocabulary for tools or resources, and the word scope appears in the normative authorization text principally as an HTTP 403 error condition, invalid scopes or insufficient permissions. There is a mechanism for saying which server may accept this credential. There is no mechanism at that layer for saying what it may do once accepted.
So the chain from intent to authority has two lossy steps and both of them are silent. A human forms an intent, which is a task: reconcile yesterday's exceptions for this merchant. The intent is translated into a grant, which is a name: the database connector. The grant is exercised as a closure, which is whatever the credential behind that name can reach. Nothing anywhere in the system records the distance between step one and step three, and no artefact produced by the pipeline has a field where such a record could go.
Why this is structural and not an oversight
The reflex on reading the above is that someone should add the missing field — annotate connectors with their reachable resource classes and be done with it. That reflex is worth arguing with, because it underestimates why the field is absent, and the reasons it is absent are the reasons this will not close on its own.
The name is the only thing nameable at that layer. A connector is written before the tasks that will use it exist. The platform does not know the customer's schema, does not know which merchant, does not know what a day means in their reconciliation window. Generality is not laziness here; it is the product. A connector that only worked for one merchant's one day of rows would not be a connector, it would be a script, and nobody would put it in a catalogue. The abstraction that makes a connector reusable is precisely the abstraction that erases the task.
The value is combinatorial and the review is linear. This is the sharpest form of the structural claim and it is arithmetic rather than opinion. A catalogue of N connectors is valuable because customers can assemble configurations out of it, and the number of distinct sets a customer can assemble grows exponentially in N. The review cost grows linearly in N, because reviews are attached to publication and publication is per-item. The quantity being sold and the quantity being reviewed are not merely different, they are different orders. No amount of additional diligence per review changes an exponent. Any fix has to change the object being granted, not the rigour with which each catalogue entry is examined.
The set has no owner on either side of the contract. Follow the artefacts. The platform's review pipeline produces per-connector approvals, and the pipeline terminates at publication. The customer's configuration surface produces an enabled set, and it has no review apparatus attached because it is a settings page. The agent runtime consumes the set and produces calls. At no point does an object exist whose content is the set, and organisations do not review things that are not objects — not because they are careless, but because a review needs something to be handed.
The friction gradient points the wrong way. Narrowing a grant costs prompts, failures, latency, support tickets and demo quality. Widening one costs nothing measurable until something goes wrong, and even then the cost lands on an incident channel rather than on the roadmap. The protocol's companion Security Best Practices document — a separate guidance text from the specification proper, and one I am citing at its 2025-11-25 revision throughout, because several of the sections relied on below were not in the version published alongside the June 2025 spec — lists bundling unrelated privileges to preempt future prompts as a common mistake, which tells you it is common; and it is common because at the moment of the decision it is the rational local move for everyone in the room. This is why the gap widens with product maturity rather than narrowing.
It is worth noticing how old the correct vocabulary is. Saltzer and Schroeder, writing in 1975, stated least privilege as the principle that every program and every user of the system should operate using the least set of privileges necessary to complete the job, and complete mediation as the requirement that every access to every object must be checked for authority. Read those two sentences against a connector catalogue. Least privilege is defined relative to the job — the task, not the integration. Complete mediation is defined relative to every object — the row, not the connector. Both principles take as given that the system has a representation of the job and a representation of the object. A tool definition has neither. The principles have not been violated so much as rendered inexpressible: there is nothing in the grant with the right shape to hold them.
And the protocol says so about itself, in language platform teams should read as directly addressed to them. Its security section states that while the protocol itself cannot enforce these security principles at the protocol level, implementors should build robust consent and authorization flows into their applications. The four principles it names — user consent and control, data privacy, tool safety, and controls on model sampling — are stated as implementor obligations rather than protocol mechanisms. The specification has told you where the responsibility sits. On a connector catalogue, the implementor is the platform.
Grants compose, and the composition is where the authority lives
Composition is the part that makes this a platform problem rather than a scoping hygiene problem, so it deserves to be developed carefully rather than asserted.
Start with the mechanical version. Give every connector two attributes it does not currently carry: the effect classes it can produce, and the resource classes it can touch. Enable a set. The interesting object is not the list — it is the graph the list induces, where an edge exists between any connector that can read something sensitive and any connector that can move data outward. Nine connectors give thirty-six pairs and eighty-four triples. Forty give seven hundred and eighty pairs and nine thousand eight hundred and eighty triples. Those are the combinatorics of the illustration and not a measurement of anybody's catalogue, but they establish the shape: the reviewed objects sit on the diagonal, and everything off the diagonal has been examined by nobody.
Now the version that actually bites, which is not combinatorial at all.
In the constructed trace, the configuration connector's output is a connection string. A connection string is not data in the sense the review was thinking about when it approved a read-only configuration tool. It is authority, serialised. The moment it lands in the agent's context, the database connector's carefully scoped credential stops being the boundary, because the agent now holds material that addresses a different database entirely — one that nobody enabled, that appears in no configuration screen, and that has no connector, no review and no log line attributing anything to this agent. The composition did not add two reachable sets together. It converted the output of one tool into the input authority of the next, which is a different operation and a much worse one.
There is a third layer, and it is the one that separates this from every integration problem the industry has already solved. A conventional integration composes two systems in code that a human wrote and that at least one other human read in review. An agent composes them at run time, according to a plan nobody wrote, chosen from tool descriptions. And the specification is explicit about the standing of those descriptions: tools represent arbitrary code execution and must be treated with appropriate caution, and descriptions of tool behaviour such as annotations should be considered untrusted unless obtained from a trusted server. The server-features text restates it normatively — clients MUST consider tool annotations to be untrusted unless they come from trusted servers. The composition engine is being steered by strings the protocol tells you not to trust.
Invariant Labs published the concrete version of that on 1 April 2025, under the name tool poisoning. Their disclosure documents three distinct mechanisms: instructions hidden inside a tool description, invisible to the user and visible to the model; tool shadowing, where a tool served by one server injects instructions that alter the agent's behaviour toward a different and trusted server, demonstrated by rerouting mail that was being sent through a separate email tool; and post-approval redefinition, where a server changes a tool's description after the client has already approved it. Two caveats belong with that citation. It is an April 2025 snapshot, and I have not re-verified which clients remain susceptible as of this writing, so nothing here should be read as a claim about any current product. And the mechanisms are the published research, not an incident at a named company.
What matters for this argument is the shape of the shadowing result rather than its severity. It says that the security property of connector A can be changed by the presence of connector B. That is the formal definition of a compositional property, and it means the per-connector review is not merely incomplete — it is answering a question whose answer is not well-defined until the set is fixed. A reviewer approving connector A in isolation cannot be right or wrong about its behaviour, because its behaviour is not yet determined.
None of this requires a compromised server, incidentally. The credential-in-config path in the opening trace involves no attacker, no poisoning and no malice. It is what the product does when it is working.
The closure is computable, which is the point
One reason to be blunt about the missing analysis is that it is not hard. The code below is not a remedy — it computes nothing that the catalogue does not already imply, and it changes no grant. It is measurement, and it exists here to make a narrower claim: that the absence of this object is a product decision rather than a technical limit.
The first tab models the tool definition as the protocol defines it, which is worth typing out because the absence is easier to see in a type than in prose. The second adds the annotation a platform would have to author itself, and computes the closure over an enabled set. The third enumerates the source-to-sink pairs — the thing nobody currently holds.
Computing the reachable set nobody computes
Pure functions, no dependencies, strict mode. This is diagnostic code: it tells you the size of the problem in an estate you already run. It does not narrow anything, and it is deliberately not the broker.
Every field the specification defines for a tool, and nothing else. Read it looking for the field that says which rows, tables, endpoints or accounts this tool may reach. The inputSchema types the arguments; the reachable set is determined by the credential the server holds, which appears nowhere in this type.
export type JsonSchema = {
readonly type: string;
readonly properties?: Readonly<Record<string, JsonSchema>>;
readonly required?: readonly string[];
};
/**
* The complete set of fields the protocol defines for a tool: name, title,
* description, inputSchema, optional outputSchema, optional annotations.
*
* Note what is absent. There is no field constraining which resources the tool
* may reach when invoked. The schema types the arguments, not the reachable set.
*/
export type ToolDefinition = {
readonly name: string;
readonly title?: string;
readonly description: string;
readonly inputSchema: JsonSchema;
readonly outputSchema?: JsonSchema;
/** Per the specification, untrusted unless the server itself is trusted. */
readonly annotations?: Readonly<Record<string, unknown>>;
};
export type Connector = {
readonly id: string;
readonly displayName: string;
readonly tools: readonly ToolDefinition[];
};Two honest limits on this code. It requires a Reach annotation that no catalogue currently emits, so running it means authoring the missing data first — which is most of the work and is exactly the point. And it models composition as pairwise, which understates the problem: authority-expansion paths chain, and a credential read at step one can make a resource reachable at step four that no pair in the enabled set contains.
What specifically fails
Eight mechanisms. The first seven are documented in the protocol's own security text or in published research rather than inferred; the eighth is mine, and it is flagged as such where it appears, because it applies the same closure argument to geography rather than reporting something anybody has written down. What makes the list worth reading as a group is that every entry is a compositional failure: a property that exists only because two things are held together.
1. The review unit does not match the consumption unit. Reviews attach to publication because publication is the event the platform controls. Sets are assembled after publication by a customer administrator using an interface with no review apparatus, because it is a settings page and settings pages do not have approval workflows attached to their aggregate state. The finding is not that anybody skipped a step. It is that the pipeline has no step whose input is the set, so there is nothing to skip.
2. The scope catalogue leaks its own blast radius. The Security Best Practices document names this directly under scope minimization — a section added after the June 2025 specification, so a reader checking the older text will not find it there. An attacker obtaining a token carrying broad scopes granted up front — because the server exposed every scope in scopes_supported and the client requested them all — gains what the document calls expanded blast radius, where a stolen broad token enables unrelated tool and resource access, together with privilege chaining and audit noise. Its list of common mistakes is worth reading as a product review checklist: publishing all possible scopes in scopes_supported, using wildcard or omnibus scopes, and bundling unrelated privileges to preempt future prompts. Note the third one particularly. Bundling to avoid prompting a user is a friction decision made by a product team, and it silently becomes an authority decision that no security review ever sees, because it was never filed as one.
3. Audience binding constrains where, not what. RFC 8707 is precise about the underlying problem: bearer tokens, the most commonly used type of OAuth access token, allow any party in possession of a token to get access to the associated resources, and an access token must only be valid for use at a specific protected resource and for a specific scope of access. Its security considerations go further and direct that, to the extent possible, the authorization server should downscope the scope value associated with an access token to the value the respective resource is able to process and needs to know. A platform that implements resource indicators perfectly has narrowed which server will accept the credential. It has not narrowed what the credential does once accepted, and the specification's own scope-vocabulary gap means there is no standard way to express the second thing at that layer.
4. Token passthrough turns a connector into a proxy. The protocol forbids it in the strongest terms available: servers MUST NOT accept any tokens that were not explicitly issued for them, and where a server calls an upstream API, it MUST NOT pass through the token it received from the client. The stated risk is that a server passing tokens without validating audience or claims can be used as a proxy for data exfiltration by an actor holding a stolen token. The reason this belongs on a composition list is that a connector by construction sits between two authority domains, and every such component is a candidate confused deputy. The prohibition is correct and it is also a standing reminder of what the architecture invites.
5. The confused deputy appears in the identity layer itself. The Security Best Practices document, in its current revision, documents a confused-deputy vulnerability that arises when four conditions hold together: a proxy using a static client ID with a third-party authorization server; MCP clients permitted to dynamically register their own client_ids; a third-party server that sets a consent cookie after the first authorization; and a proxy that does not implement per-client consent. With all four in place the consent screen is skipped and the authorization code is redirected to an attacker-registered redirect_uri. The normative fix is that proxy servers MUST implement per-client consent, maintaining a registry of approved client_id values per user and checking it before initiating the third-party flow. Every one of the four conditions is individually a reasonable engineering choice. The vulnerability is the conjunction, which is the thesis of this essay expressed inside the authorization stack rather than above it.
6. Session state drifts into becoming authorization. The protocol separates the two normatively: servers implementing authorization MUST verify all inbound requests, and MUST NOT use sessions for authentication. Session IDs must be secure and non-deterministic, and should be bound to user-specific information using a key format such as user id joined to session id. This is on the list because the drift is compositional in the organisational sense — session handling is usually owned by the runtime team and authorization by the identity team, and the failure lives in the seam between two correct components.
7. The client is a connector too, and it fetches attacker-supplied URLs. During authorization discovery a client fetches URLs the server supplies: the resource_metadata URL from a WWW-Authenticate header, authorization_servers URLs, token and authorization endpoints. The Security Best Practices document — again in the current revision, which added a server-side request forgery section the June 2025 text did not carry — names cloud metadata endpoints at 169.254.169.254 as an exfiltration target, directs that clients should block private and reserved IP ranges per RFC 9728 section 7.7, and warns that attackers exploit encoding tricks — octal, hex, IPv4-mapped IPv6 — that custom parsers often miss. A platform reviewing its catalogue tends to think of the connectors as the attack surface and the client as the reviewer. The client is server-side software making outbound requests to addresses it was handed, which is the same shape as everything else on this list.
8. The set crosses boundaries the set was never checked against. This one is not in anybody's security text — it is my own extension of the argument, and it should be read as an inference rather than a citation. Regional reach is a reachability property and it composes exactly like every other one. A connector reviewed against a North American deployment, a connector fronting an Indian data estate and a connector whose credential resolves to a Gulf sovereign region are individually correct in their own regional reviews. Their intersection — the set an administrator enabled — is a data path across three regions that no regional architecture review ever held, for the same reason as everything above: the regional reviews were attached to connectors, and the crossing is a property of the set. This is not a legal argument. It is the same closure problem with geography as the resource class, and it is the version most likely to be discovered by a customer rather than by the platform.
The synthesis is the reason to list all eight. Every one of these was written down by the people who designed the protocol. They saw the class clearly, and they said in the specification's own opening that the protocol cannot enforce these principles at the protocol level and that implementors should build the flows. What has not happened is the step after that: nobody has made the enabled set a first-class object that anything in the pipeline can hold, review, diff or attest to.
What the field already knows near this
The uncomfortable part of this argument is that almost none of it is new. The vocabulary, the failure mode and the cryptographic construction all predate the current wave by decades, and it is worth laying them out precisely because the gap is not a research gap.
Saltzer and Schroeder gave the two principles in 1975, and they are quoted above rather than paraphrased for a reason: least privilege is stated relative to the job, and complete mediation relative to every object. Those are the two nouns a connector catalogue does not have. Fifty-one years later the industry ships a grant primitive that can express neither, and does so not out of ignorance but because the primitive was designed for reusability across unknown tasks, which is the direct negation of both.
The confused deputy is the canonical name for the failure where a component exercises its own authority under someone else's intent; Norman Hardy's 1988 note in ACM SIGOPS Operating Systems Review is the usual citation, and I list it below as a reference rather than quoting from it, because I was not able to obtain the full text in preparing this and will not reconstruct a paper's argument from memory. The live, verified instance is the protocol's own confused-deputy section, described above.
The construction that most directly answers the attenuation problem is also published and deployed. Macaroons, from the 2014 Network and Distributed System Security Symposium paper by Birgisson, Politz, Erlingsson, Taly, Vrable and Lentczner, are bearer credentials that embed caveats which attenuate and contextually confine when, where, by who, and for what purpose a target service should authorize requests. They are built from nested, chained MACs — HMACs, for instance — in a manner the authors describe as highly efficient, easy to deploy, and widely applicable, and the paper explicitly discusses strengthening existing mechanisms such as OAuth2. The properties that matter for a connector catalogue are that the holder can attenuate a credential without contacting the issuer, and that the constraints travel with the credential and are verifiable at the resource. That is twelve years old.
The protocol's guidance also already prescribes the right direction, which makes the gap between that guidance and shipped catalogues the sharpest single observation in this piece. Under scope minimization its mitigation is not a better toolbelt — it is the abolition of the toolbelt. Start from a minimal initial scope set, for example a tools-basic scope containing only low-risk discovery and read operations. Then elevate incrementally, through targeted WWW-Authenticate scope challenges issued when a privileged operation is first attempted. Servers are told to emit precise scope challenges and to avoid returning the full catalogue, and to accept down-scoped tokens.
Read that as an architecture rather than as a checklist and it is a negotiation: authority is requested at the moment of use, for the operation actually attempted, and granted narrowly in response to a specific challenge. It is the correct shape. It is also, as far as I can tell from public documentation, not the shape of the shipping connector catalogues whose documentation I could reach, which grant the belt up front and then rely on downstream controls. That is a statement about the documentation available to me, not about every catalogue in existence.
One more piece of the field's existing knowledge belongs here. RFC 9700, the IETF's OAuth security best current practice of January 2025, makes least privilege normative for tokens: privileges associated with an access token should be restricted to the minimum required for the particular application or use case, and access tokens should be audience-restricted to a specific resource server or, failing that, to a small set of them. It also recommends binding tokens to their holder as well as their audience, through mutual TLS or DPoP, and requires that refresh tokens for public clients be sender-constrained or rotated. Taken together with resource indicators, the industry has standardised two of the three bindings a grant needs.
Where this argument runs out
The claims above are architectural, and architectural claims are cheap unless the person making them says what would show them wrong. Five things.
I have no census, and I distrust the ones circulating. I cannot tell you how many catalogues exist, how many connectors the median one carries, or how large a typical enabled set is. No primary registry census was located in preparing this. Several percentages describing the share of servers in the wild carrying command-injection or credential-exposure flaws are in circulation, generally attributed to vendor scans; I could not trace one to a primary publication with a stated methodology and sample frame, and I have therefore used none of them. If someone quotes you such a figure, the two questions are what was scanned and how it was selected.
There is no incident behind this, and there should not need to be. I am not aware of, and did not verify, any public advisory or CVE at a named cloud or AI platform attributing a breach to tool-grant over-reach or to tool poisoning. The argument here is built from documented attack classes in the specification and from one published research disclosure, plus the structure of the tool definition itself. If the argument only lands once there is a named victim, it has not landed, and waiting for one is a poor engineering strategy in any case.
The strongest genuine counter is that closures may be small in practice. Suppose most enabled sets are two or three connectors rather than nine; suppose most connector credentials are already narrow because the platform provisioned them per-tenant against tight roles; suppose agents rarely chain across connectors in a single run. Under those conditions the combinatorics never bite and this essay is an elegant description of a problem nobody has. I believe that is false, but I cannot demonstrate it is false from public data, and I would rather say so than dress an intuition as a finding.
The measurement that would settle it has not been taken. The prediction under test is this: if a platform instrumented the closure — computing, for each enabled set at configuration time, the count of reachable resource classes against the count its declared tasks actually name — the median ratio would be large enough that the reviewed union and the exercised closure could not sensibly be called the same object. I have not measured that, and no number in this piece is such a measurement. Two distributions would settle the question and only platforms can publish them: the distribution of enabled-set sizes, and the per-connector ratio of reachable resources to those a median task uses. Both are computable from data these companies already hold.
Three things would falsify the argument as stated. First, a catalogue whose tool definitions carry a resource-reach declaration and whose grants are minted per task would make the central claim locally wrong, and I would want to study it rather than defend the claim. Second, evidence that agent runs are effectively single-connector in practice would remove the composition premise entirely. Third, evidence that connector credentials faithfully carry the calling user's own authority rather than a service identity would collapse the amplification argument — though note that the specification forbids passing the client's token through to upstream APIs, so this particular escape route is closed by the protocol itself, which is informative about how hard the problem is rather than reassuring.
One limit on the remedy space, stated here so the companion piece cannot be read as ignoring it. Narrowing grants has a real, immediate and asymmetric cost: more consent interrupts, more mid-task failures, more latency, worse demonstrations, and a support burden that lands on the team that shipped the narrowing. Bundling privileges to avoid future prompts appears on the protocol's own list of common mistakes precisely because it is the locally rational choice. Any answer has to beat that argument on its own terms rather than pretend it is not there.
The decision that has never been framed as one
Which returns to the objection held back earlier: that the enabled set is the customer's configuration and therefore the customer's problem.
As a statement about contracts that is often true and it does not help anybody. Consider what a customer actually has to work with when someone asks the authority question — who authorised this agent to touch that, and how far could it have gone. The customer's answer must be assembled from the primitives the platform chose to emit. If the only primitive is a connector, the answer is a list of connector names, which is not an answer to the question asked; it is the union restated, and the union is the thing that was never the issue. Every customer building an authority story today is reconstructing one from parts that were not designed to carry it, and they are all reconstructing it differently, which is why no two of their answers can be compared.
The platform is the only party who can change this, and at the moment it is the only party not being asked to. Regulators ask deployers. Auditors ask deployers. Enterprise security questionnaires ask deployers. The party who chose the grammar is downstream of all of it, and the choice was made in a product review that only ever saw one item at a time.
That is the reframe worth leaving with. A connector catalogue is not a list of features. It is a language — a claim about what units of authority exist in the world, imposed on every organisation that builds on it. Shipping the connector as the unit of grant fixes the grammar available to every downstream buyer, every auditor and every incident review for as long as the catalogue is in market. It is one of the highest-leverage product decisions on the platform's roadmap, and it has been made by default, item by item, by people who were each looking at exactly one connector.
The shape of the alternative is visible from here without being built here. The grant stops being a catalogue entry and becomes something minted at the moment of use: narrow by construction, attenuable by the holder without a round trip to the issuer, carrying its constraints with it, and verifiable at the resource rather than trusted at the perimeter. Every ingredient exists — the caveat construction from 2014, the audience binding of RFC 8707, the holder binding of RFC 9700, and the protocol's own challenge-driven elevation. Assembling them into something a platform can ship is a broker, and building it is a separate piece of work with its own arguments and its own costs.
That construction is the companion to this one, forthcoming: A capability broker for platforms — minting narrow grants instead of shipping wide ones. This piece is the teardown, and a teardown that hands you the answer in its last section has not made you feel the problem for long enough to want a good one.
For now the smallest useful action is also the cheapest. Take one enabled set from one real customer configuration, put the nine or twelve credentials behind it on a single page, and compute what they reach. Not what they were approved for — what they reach. Nobody in the pipeline has ever done that, and the number will tell you whether the rest of this argument is worth your quarter.