From 7fedb1b51a7e120ec1af8dd738a0371e9143ac49 Mon Sep 17 00:00:00 2001 From: Alan Blount Date: Sun, 5 Apr 2026 03:37:18 +0000 Subject: [PATCH 1/2] fix(security): remove allow-same-origin from MCP Apps sandbox iframes The Lit sample and shared sandbox proxy included allow-same-origin in iframe sandbox attributes, violating the MCP Apps guide/spec: - Lit outer iframe: removed sandbox attribute entirely (guide says don't sandbox the proxy iframe) - Lit sendSandboxResourceReady: allow-scripts only (was allow-scripts allow-forms allow-popups allow-modals allow-same-origin) - Shared sandbox.ts inner iframe default: allow-scripts only (was allow-scripts allow-same-origin allow-forms) The Angular sample already correctly used sandbox: 'allow-scripts'. Confirmed against MCP Apps spec (SEP-1865) and AppBridge SDK docs. Fixes security discrepancy found by Gemini Code Assist review on #1062. --- .../ui/custom-components/mcp-apps-component.ts | 3 +-- samples/client/shared/mcp_apps_inner_iframe/sandbox.ts | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/samples/client/lit/custom-components-example/ui/custom-components/mcp-apps-component.ts b/samples/client/lit/custom-components-example/ui/custom-components/mcp-apps-component.ts index 201738b6d..137c44cca 100644 --- a/samples/client/lit/custom-components-example/ui/custom-components/mcp-apps-component.ts +++ b/samples/client/lit/custom-components-example/ui/custom-components/mcp-apps-component.ts @@ -76,7 +76,6 @@ export class McpApp extends Root { `; @@ -176,7 +175,7 @@ export class McpApp extends Root { // 4. Send the Inner HTML UI resource to the sandbox to spin up the actual app. await this.bridge.sendSandboxResourceReady({ html: this.htmlContent, - sandbox: "allow-scripts allow-forms allow-popups allow-modals allow-same-origin" + sandbox: "allow-scripts" }); } diff --git a/samples/client/shared/mcp_apps_inner_iframe/sandbox.ts b/samples/client/shared/mcp_apps_inner_iframe/sandbox.ts index fd52381d5..421e72b60 100644 --- a/samples/client/shared/mcp_apps_inner_iframe/sandbox.ts +++ b/samples/client/shared/mcp_apps_inner_iframe/sandbox.ts @@ -63,7 +63,7 @@ if (!disableSelfTest) { // iframe on a separate origin. It creates an inner iframe for untrusted HTML content. const inner = document.createElement("iframe"); inner.style.cssText = "width:100%; height:100%; border:none;"; -inner.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms"); +inner.setAttribute("sandbox", "allow-scripts"); document.body.appendChild(inner); const RESOURCE_READY_NOTIFICATION: McpUiSandboxResourceReadyNotification["method"] = From fd2dd0cddcd6988a9dc7f9c7cbc92ed3f76b040d Mon Sep 17 00:00:00 2001 From: alan blount Date: Mon, 6 Apr 2026 18:49:07 -0700 Subject: [PATCH 2/2] Apply suggestions from code review Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../ui/custom-components/mcp-apps-component.ts | 2 +- samples/client/shared/mcp_apps_inner_iframe/sandbox.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/client/lit/custom-components-example/ui/custom-components/mcp-apps-component.ts b/samples/client/lit/custom-components-example/ui/custom-components/mcp-apps-component.ts index 137c44cca..aad77bfef 100644 --- a/samples/client/lit/custom-components-example/ui/custom-components/mcp-apps-component.ts +++ b/samples/client/lit/custom-components-example/ui/custom-components/mcp-apps-component.ts @@ -175,7 +175,7 @@ export class McpApp extends Root { // 4. Send the Inner HTML UI resource to the sandbox to spin up the actual app. await this.bridge.sendSandboxResourceReady({ html: this.htmlContent, - sandbox: "allow-scripts" + sandbox: "allow-scripts allow-forms allow-popups allow-modals" }); } diff --git a/samples/client/shared/mcp_apps_inner_iframe/sandbox.ts b/samples/client/shared/mcp_apps_inner_iframe/sandbox.ts index 421e72b60..353fefa64 100644 --- a/samples/client/shared/mcp_apps_inner_iframe/sandbox.ts +++ b/samples/client/shared/mcp_apps_inner_iframe/sandbox.ts @@ -63,7 +63,7 @@ if (!disableSelfTest) { // iframe on a separate origin. It creates an inner iframe for untrusted HTML content. const inner = document.createElement("iframe"); inner.style.cssText = "width:100%; height:100%; border:none;"; -inner.setAttribute("sandbox", "allow-scripts"); +inner.setAttribute("sandbox", "allow-scripts allow-forms allow-popups allow-modals"); document.body.appendChild(inner); const RESOURCE_READY_NOTIFICATION: McpUiSandboxResourceReadyNotification["method"] =