From 44d5faeb7d589dbd266584423f232ae07239ba46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milorad=20FIlipovi=C4=87?= Date: Tue, 30 Jun 2026 15:30:10 +0200 Subject: [PATCH] fix(core): Narrow mcp apps frame domains (no-changelog) (#33123) --- packages/@n8n/mcp-apps/README.md | 12 +++++++----- packages/@n8n/mcp-apps/src/server/constants.ts | 12 ++++++------ 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/@n8n/mcp-apps/README.md b/packages/@n8n/mcp-apps/README.md index b382ae34778..ce7faf59e37 100644 --- a/packages/@n8n/mcp-apps/README.md +++ b/packages/@n8n/mcp-apps/README.md @@ -85,11 +85,13 @@ URL handling is locked down by `isAllowedWorkflowUrl` in host are accepted, both when reading the tool result and right before calling `openLink`. This is defense in depth on top of the host's own validation. -The workflow preview iframe uses a server-provided `previewUrl` when available. -Otherwise it uses the existing n8n preview service because instance routes are -commonly blocked or unreachable from MCP hosts. The resource metadata declares -broad `frameDomains` for `http` and `https` so hosts that enforce MCP Apps CSP -can load instance-specific or configured preview URLs. The framed n8n server's +The workflow preview iframe loads the shared n8n preview service +(`WORKFLOW_PREVIEW_ORIGIN`). The preview is instance-agnostic: the workflow +graph is pushed into the iframe via `postMessage` rather than fetched from the +instance, so a single origin renders both cloud and self-hosted workflows. The +resource metadata therefore declares exactly one `frameDomains` entry — the +preview-service origin. Keep this list narrow: MCP hosts (e.g. the ChatGPT +connector review) reject broad or wildcard frame domains. The framed server's own frame policy still applies, so the app falls back to the open-workflow button when the preview cannot load. diff --git a/packages/@n8n/mcp-apps/src/server/constants.ts b/packages/@n8n/mcp-apps/src/server/constants.ts index 340613905ef..90d4c4edd6e 100644 --- a/packages/@n8n/mcp-apps/src/server/constants.ts +++ b/packages/@n8n/mcp-apps/src/server/constants.ts @@ -3,9 +3,9 @@ export const RESOURCE_URI_META_KEY = 'ui/resourceUri'; export const WORKFLOW_PREVIEW_APP_URI = 'ui://workflow-preview/workflow-preview.html'; export const WORKFLOW_PREVIEW_ORIGIN = 'https://n8n-preview-service.internal.n8n.cloud'; -export const WORKFLOW_PREVIEW_FRAME_DOMAINS = [ - WORKFLOW_PREVIEW_ORIGIN, - 'https://*', - 'http://localhost:*', - 'http://127.0.0.1:*', -] as const; +// Scoped to the single preview-service origin (CSP `frame-src`). The preview is +// instance-agnostic: workflow data is pushed into the iframe via postMessage, so +// the same origin renders cloud and self-hosted workflows without needing the +// instance origin framed. Keep this narrow — MCP hosts reject broad/wildcard +// frame domains. +export const WORKFLOW_PREVIEW_FRAME_DOMAINS = [WORKFLOW_PREVIEW_ORIGIN] as const;