From 9354e2022a5afb6f981e4ebbc6efc05db4751a7f Mon Sep 17 00:00:00 2001 From: arussac Date: Sun, 31 May 2026 15:51:07 +0200 Subject: [PATCH] tr --- frontend/src/components/RichContent.vue | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/RichContent.vue b/frontend/src/components/RichContent.vue index f2aa96a..bca13b1 100644 --- a/frontend/src/components/RichContent.vue +++ b/frontend/src/components/RichContent.vue @@ -4,9 +4,12 @@ Renders paid HTML/CSS or JS messages inside a FIXED-SIZE sandboxed iframe. Sandbox policy (never deviate): - - htmlcss tier: sandbox="" (empty) → scripts are INERT (honours README "pas de script"). + - htmlcss tier: sandbox="" (empty) → scripts are INERT. A meta CSP reinforces this. - js tier: sandbox="allow-scripts" ONLY → script runs in a NULL origin and cannot touch the parent (no allow-same-origin, ever). + NO meta CSP for js mode: Chromium silently blocks 'unsafe-inline' + in null-origin srcdoc iframes despite it being declared; the sandbox + without allow-same-origin is the real isolation boundary. We NEVER combine allow-scripts with allow-same-origin (that would re-grant parent access and defeat isolation). A runtime assertion below guards against it. @@ -44,12 +47,14 @@ if (import.meta.env.DEV) { } const srcdoc = computed(() => { - // In-document CSP as a second layer (the sandbox is the primary boundary). - const csp = - props.mode === 'js' - ? "default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; img-src data: https:; font-src data:;" - : "default-src 'none'; script-src 'none'; style-src 'unsafe-inline'; img-src data: https:; font-src data:;"; - return `${props.content}`; + // For htmlcss mode: meta CSP blocks scripts as a second layer (sandbox="" already blocks them too). + // For js mode: NO meta CSP — the null-origin sandbox (allow-scripts without allow-same-origin) + // is the real security boundary; adding a meta CSP with default-src 'none' in a null-origin + // srcdoc iframe causes Chromium to silently block inline scripts despite 'unsafe-inline'. + const metaCsp = props.mode === 'js' + ? '' + : ''; + return `${metaCsp}${props.content}`; });