From 06526a4eb82fbd44eccf620a00b6d41e17311921 Mon Sep 17 00:00:00 2001 From: Julia Pagnucco Date: Mon, 28 Sep 2026 21:08:07 +0000 Subject: [PATCH 1/2] Document cross-origin tool exposure and two-sided opt-in in Section 6.3.4 --- index.bs | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/index.bs b/index.bs index ce4b956..f3abf4d 100644 --- a/index.bs +++ b/index.bs @@ -1885,9 +1885,57 @@ This creates a personalization-to-fingerprinting pipeline where sites can extrac

Violation of Same-Origin Boundaries

-

- TODO: Document risks and implications of [=agents=] carrying state from one origin to another. Detail how tools executed on one origin may carry state from another origin, potentially leading to data leakage or same-origin policy bypasses if not handled securely by the [=user agent=]. This section should probably talk about the WebMCP permissions policy and other cross-origin opt in mechanisms. -

+The Same-Origin Policy (SOP) is the foundational security boundary of the web platform, isolating documents of different [=origins=] so that one [=origin=] cannot inspect or manipulate the state of another without explicit consent. In the context of WebMCP, potential violations of same-origin boundaries arise across two distinct pathways: + +
    +
  1. + Direct Cross-Document / Cross-Origin Tool Exposure: Where an in-page script (such as an in-page [=agent=]) in one {{Document}} attempts to discover or invoke WebMCP tools registered by another {{Document}} in the frame tree ({{ModelContext/getTools()}} and {{ModelContext/executeTool()}}). +
  2. +
  3. + Agent-Mediated Cross-Origin State Transfer: Where an external or browser-integrated [=agent=] ([=browser's agent=]) interacts with multiple [=origins=] over the course of a task and carries state derived from one [=origin=] into tool invocations on another [=origin=]. This is not a WebMCP-specific threat. +
  4. +
+ +
In-Page Cross-Origin Tool Exposure and the Two-Sided Opt-In Model
+ +By default, WebMCP enforces strict [=same origin=] isolation: a tool registered via document.{{Document/modelContext}}.{{ModelContext/registerTool()}} is only visible to and executable by {{Document}}s that are [=same origin=] with the registering {{Document}} (tool owner). Cross-origin {{Document}}s cannot discover, observe {{ModelContext/toolchange}} events for, or execute a tool unless three independent access-control gates are satisfied: + +
    +
  1. + Embedder Delegation via Permissions Policy (allow="tools"): Access to all WebMCP APIs ({{ModelContext/registerTool()}}, {{ModelContext/getTools()}}, and {{ModelContext/executeTool()}}) is gated behind the "{{tools}}" [=policy-controlled feature=], whose [=policy-controlled feature/default allowlist=] is [=default allowlist/'self'=]. Consequently, a cross-origin <{iframe}> cannot register or expose tools—nor will an ancestor's {{ModelContext/getTools()}} traversal inspect that subframe—unless the embedding {{Document}} explicitly delegates the "{{tools}}" feature to the subframe via <iframe allow="tools">. +
  2. +
  3. + Tool Provider Opt-In ({{ModelContextRegisterToolOptions/exposedTo}}): A {{Document}} registering a tool must explicitly opt in to cross-origin exposure by specifying the permitted caller [=origins=] in {{ModelContextRegisterToolOptions/exposedTo}}. Each listed [=origin=] must be a valid, [$is origin potentially trustworthy?|potentially trustworthy$] [=origin=]. During both discovery ({{ModelContext/getTools()}}) and invocation ({{ModelContext/executeTool()}}), the [=user agent=] evaluates the [=tool is exposed to an origin=] algorithm, ensuring that only callers whose [=Document/origin=] is [=same origin=] with the tool owner or explicitly listed in {{ModelContextRegisterToolOptions/exposedTo}} can access the tool. +
  4. +
  5. + Tool Consumer Opt-In ({{ModelContextGetToolOptions/fromOrigins}}): Even when an embedded cross-origin {{Document}} has been delegated allow="tools" and has exposed a tool to its parent [=origin=] via {{ModelContextRegisterToolOptions/exposedTo}}, {{ModelContext/getTools()}} only returns tools from [=same origin=] {{Document}}s by default. To discover tools from a cross-origin descendant [=navigable=], the calling {{Document}} must also explicitly list the target [=origin=] in {{ModelContextGetToolOptions/fromOrigins}}. +
  6. +
+ +**Why Two-Sided Opt-In Matters**: Requiring mutual consent from both the tool provider ({{ModelContextRegisterToolOptions/exposedTo}}) and the tool consumer ({{ModelContextGetToolOptions/fromOrigins}}) prevents unsolicited tool-list pollution. Without consumer opt-in ({{ModelContextGetToolOptions/fromOrigins}}), a compromised or untrusted third-party <{iframe}> could unilaterally expose tools with deceptive names or prompt-injected descriptions ([[#metadata-description-attacks]]) into the parent page's {{ModelContext/getTools()}} results. Conversely, without provider opt-in ({{ModelContextRegisterToolOptions/exposedTo}}), a malicious parent page could invoke internal tools inside an embedded third-party widget that were intended only for [=same origin=] use. + +```js +// 1. Parent document (https://app.example.com) explicitly delegates the "tools" +// feature to the embedded widget (