From 529d7271899e1285f65fefa580176ac4a3eb760d Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Sun, 6 Nov 2022 23:10:34 +0100 Subject: [PATCH] Bugfix CSP handling Nextcloud<24 for #631 and #633 --- dev/boot.js | 17 ++++++++------- .../lib/Controller/PageController.php | 21 ++++++++++++------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/dev/boot.js b/dev/boot.js index 395cf5263..af5fb5c8d 100644 --- a/dev/boot.js +++ b/dev/boot.js @@ -9,6 +9,13 @@ const layout = doc.cookie.match(/(^|;) ?rllayout=([^;]+)/) || '', badBrowser = () => doc.location.replace('./?/BadBrowser'), + showError = msg => { + let div = eId('loading-error'); + div.append(' ' + msg); + eId('loading').hidden = true; + div.hidden = false; + }, + loadScript = src => { if (!src) { throw new Error('src should not be empty.'); @@ -44,13 +51,7 @@ window.rl = { initData: appData => { RL_APP_DATA = appData; const url = appData.StaticLibsJs, - cb = () => rl.app ? rl.app.bootstart() : badBrowser(), - div = eId('loading-error'), - showError = msg => { - div.append(' ' + msg); - eId('loading').hidden = true; - div.hidden = false; - }; + cb = () => rl.app ? rl.app.bootstart() : badBrowser(); loadScript(url) .then(() => loadScript(url.replace('/libs.', `/${admin?'admin':'app'}.`))) .then(() => appData.PluginsLink ? loadScript(appData.PluginsLink) : Promise.resolve()) @@ -73,6 +74,6 @@ window.rl = { }; loadScript(`./?/${admin ? 'Admin' : ''}AppData/0/${Math.random().toString().slice(2)}/`) - .then(() => 0); + .catch(e => showError(e)); })(document); diff --git a/integrations/nextcloud/snappymail/lib/Controller/PageController.php b/integrations/nextcloud/snappymail/lib/Controller/PageController.php index 188d9330e..52004a7e9 100644 --- a/integrations/nextcloud/snappymail/lib/Controller/PageController.php +++ b/integrations/nextcloud/snappymail/lib/Controller/PageController.php @@ -55,16 +55,12 @@ class PageController extends Controller $sAppCssMin = $oConfig->Get('labs', 'use_app_debug_css', false) ? '' : '.min'; $sLanguage = $oActions->GetLanguage(false); - $sScriptNonce = \OC::$server->getContentSecurityPolicyNonceManager()->getNonce(); -// $sScriptNonce = \SnappyMail\UUID::generate(); -// \RainLoop\Service::setCSP($sScriptNonce); - $params = [ 'Admin' => $bAdmin ? 1 : 0, 'LoadingDescriptionEsc' => \htmlspecialchars($oConfig->Get('webmail', 'loading_description', 'SnappyMail'), ENT_QUOTES|ENT_IGNORE, 'UTF-8'), 'BaseTemplates' => \RainLoop\Utils::ClearHtmlOutput($oServiceActions->compileTemplates($bAdmin)), 'BaseAppBootScript' => \file_get_contents(APP_VERSION_ROOT_PATH.'static/js'.($sAppJsMin ? '/min' : '').'/boot'.$sAppJsMin.'.js'), - 'BaseAppBootScriptNonce' => $sScriptNonce, + 'BaseAppBootScriptNonce' => \OC::$server->getContentSecurityPolicyNonceManager()->getNonce(), 'BaseLanguage' => $oActions->compileLanguage($sLanguage, $bAdmin), 'BaseAppBootCss' => \file_get_contents(APP_VERSION_ROOT_PATH.'static/css/boot'.$sAppCssMin.'.css'), 'BaseAppThemeCssLink' => $oActions->ThemeLink($bAdmin), @@ -75,6 +71,8 @@ class PageController extends Controller ) ]; +// \OCP\Util::addScript('snappymail', '../app/snappymail/v/'.APP_VERSION.'/static/js'.($sAppJsMin ? '/min' : '').'/boot'.$sAppJsMin); + // Nextcloud html encodes, so addHeader('style') is not possible // \OCP\Util::addHeader('style', ['id'=>'app-boot-css'], \file_get_contents(APP_VERSION_ROOT_PATH.'static/css/boot'.$sAppCssMin.'.css')); \OCP\Util::addHeader('link', ['type'=>'text/css','rel'=>'stylesheet','href'=>\RainLoop\Utils::WebStaticPath('css/'.($bAdmin?'admin':'app').$sAppCssMin.'.css')], ''); @@ -83,10 +81,17 @@ class PageController extends Controller $response = new TemplateResponse('snappymail', 'index_embed', $params); $csp = new ContentSecurityPolicy(); - $csp->addAllowedScriptDomain("'self'"); - \method_exists($csp, 'useStrictDynamic') && $csp->useStrictDynamic(true); // NC24+ +// $csp->addAllowedScriptDomain("'self'"); + // CSP level 3 + \method_exists($csp, 'useStrictDynamic') + ? $csp->useStrictDynamic(true) // NC24+ + : $csp->addAllowedScriptDomain("'strict-dynamic'"); + // Else CSP level 2 + $csp->addAllowedScriptDomain("'unsafe-inline'"); // ignored by CSP 3 'strict-dynamic' $csp->allowEvalScript(true); // $csp->addAllowedScriptDomain("'unsafe-eval'"); - $csp->addAllowedStyleDomain("'self'"); +// $csp->addAllowedStyleDomain("'self'"); +// $csp->addAllowedStyleDomain("'unsafe-inline'"); +// $csp->addAllowedImageDomain("data:"); $response->setContentSecurityPolicy($csp); return $response;