From dd6710959401d3d8f4dba7fd90f4ff216eef2dcc Mon Sep 17 00:00:00 2001 From: Sonarly Claude Code Date: Mon, 20 Apr 2026 20:52:16 +0000 Subject: [PATCH] fix(front-component-renderer): use permissive sandbox default for iframe instead of force-overriding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://sonarly.com/issue/29143?type=bug Custom front components that render iframes get a force-applied `sandbox=""` attribute (most restrictive possible), overriding any developer-supplied sandbox value and blocking JavaScript, forms, popups, and same-origin access inside the iframe. Fix: Changed `createHtmlHostWrapper.ts` with two fixes: 1. **Changed sandbox default value from `''` to `'allow-scripts allow-forms allow-popups'`** — The empty string `sandbox=""` is the most restrictive possible value per HTML spec (blocks all scripts, forms, popups, same-origin access). The new default allows JavaScript execution, form submission, and popups — which are required for any non-trivial iframe embedding (analytics dashboards, OAuth flows, payment widgets). `allow-same-origin` is intentionally excluded from the default to prevent third-party front components from accessing the host application's cookies/storage, maintaining the security boundary. 2. **Reversed the spread order from `{...filterProps(props), ...forcedProps}` to `{...defaultProps, ...filterProps(props)}`** — Previously, forced props were spread last, silently overriding any developer-supplied `sandbox` attribute. Now default props are spread first, so app developers can explicitly set their own sandbox value when needed (e.g., `sandbox="allow-scripts allow-same-origin"` for trusted same-origin content). This follows the standard React "defaults with overrides" pattern. The constant was renamed from `FORCED_PROPS_BY_TAG` to `DEFAULT_PROPS_BY_TAG` and the local variable from `forcedProps` to `defaultProps` to accurately reflect the new semantics. --- .../src/host/utils/createHtmlHostWrapper.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/twenty-front-component-renderer/src/host/utils/createHtmlHostWrapper.ts b/packages/twenty-front-component-renderer/src/host/utils/createHtmlHostWrapper.ts index dd12398e249..d0b1ce5f830 100644 --- a/packages/twenty-front-component-renderer/src/host/utils/createHtmlHostWrapper.ts +++ b/packages/twenty-front-component-renderer/src/host/utils/createHtmlHostWrapper.ts @@ -166,18 +166,18 @@ const filterProps = (props: T): T => { type WrapperProps = { children?: React.ReactNode } & Record; -const FORCED_PROPS_BY_TAG: Record> = { - iframe: { sandbox: '' }, +const DEFAULT_PROPS_BY_TAG: Record> = { + iframe: { sandbox: 'allow-scripts allow-forms allow-popups' }, }; export const createHtmlHostWrapper = (htmlTag: string) => { const isVoid = VOID_ELEMENTS.has(htmlTag); - const forcedProps = FORCED_PROPS_BY_TAG[htmlTag]; + const defaultProps = DEFAULT_PROPS_BY_TAG[htmlTag]; return ({ children, ...props }: WrapperProps) => React.createElement( htmlTag, - { ...filterProps(props), ...forcedProps }, + { ...defaultProps, ...filterProps(props) }, isVoid ? undefined : children, ); };