diff options
| author | 2025-08-09 21:47:39 +0200 | |
|---|---|---|
| committer | 2025-08-09 21:47:39 +0200 | |
| commit | 2b85a50ed72982ab0c0f9ef98c7ed1e15f21bf5f (patch) | |
| tree | 7bb8412d5b14142a384e0da8cb6255802935d053 | |
| parent | 1030973d903c746d4fb10b863c7b9aebb5c448e1 (diff) | |
Show warning when unsafe CSP policy is in use (#7804)
* Show warning when unsafe CSP policy is in use
* Fix bare markdown URL
* i18n: fr
* Minor i18n: fr
* Add target="_blank" to i18n strings
---------
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
39 files changed, 92 insertions, 16 deletions
diff --git a/app/FreshRSS.php b/app/FreshRSS.php index 06557dbe1..bff9f1b18 100644 --- a/app/FreshRSS.php +++ b/app/FreshRSS.php @@ -34,6 +34,7 @@ class FreshRSS extends Minz_FrontController { // Relax Content Security Policy to allow external images if a custom logo HTML is used Minz_ActionController::_defaultCsp([ 'default-src' => "'self'", + 'frame-ancestors' => "'none'", 'img-src' => '* data:', ]); } diff --git a/app/Models/SystemConfiguration.php b/app/Models/SystemConfiguration.php index 7c7862b8a..d5dd0f0d6 100644 --- a/app/Models/SystemConfiguration.php +++ b/app/Models/SystemConfiguration.php @@ -27,6 +27,7 @@ declare(strict_types=1); * @property-read string $salt * @property-read bool $simplepie_syslog_enabled * @property bool $unsafe_autologin_enabled + * @property-read bool $suppress_csp_warning * @property array<string> $trusted_sources * @property array<string,array<string,mixed>> $extensions */ diff --git a/app/i18n/cs/gen.php b/app/i18n/cs/gen.php index 540970b56..282e6743b 100644 --- a/app/i18n/cs/gen.php +++ b/app/i18n/cs/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => 'Žádné štítky', 'new_article' => 'Jsou dostupné nové články, klikněte pro obnovení stránky.', 'should_be_activated' => 'JavaScript musí být povolen', + 'unsafe_csp_header' => 'The CSP header in use is unsafe and FreshRSS may be vulnerable to XSS attacks. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">See documentation</a>', // TODO ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/i18n/de/gen.php b/app/i18n/de/gen.php index 1ead9abeb..45fc9540b 100644 --- a/app/i18n/de/gen.php +++ b/app/i18n/de/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => 'Keine Labels', 'new_article' => 'Es gibt neue verfügbare Artikel. Klicken Sie, um die Seite zu aktualisieren.', 'should_be_activated' => 'JavaScript muss aktiviert sein', + 'unsafe_csp_header' => 'The CSP header in use is unsafe and FreshRSS may be vulnerable to XSS attacks. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">See documentation</a>', // TODO ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/i18n/el/gen.php b/app/i18n/el/gen.php index 1d67b514d..ea93a0002 100644 --- a/app/i18n/el/gen.php +++ b/app/i18n/el/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => 'No labels', // TODO 'new_article' => 'There are new articles available, click to refresh the page.', // TODO 'should_be_activated' => 'JavaScript must be enabled', // TODO + 'unsafe_csp_header' => 'The CSP header in use is unsafe and FreshRSS may be vulnerable to XSS attacks. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">See documentation</a>', // TODO ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/i18n/en-us/gen.php b/app/i18n/en-us/gen.php index c6305a248..7e7b55a11 100644 --- a/app/i18n/en-us/gen.php +++ b/app/i18n/en-us/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => 'No labels', // IGNORE 'new_article' => 'There are new articles available, click to refresh the page.', // IGNORE 'should_be_activated' => 'JavaScript must be enabled', // IGNORE + 'unsafe_csp_header' => 'The CSP header in use is unsafe and FreshRSS may be vulnerable to XSS attacks. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">See documentation</a>', // IGNORE ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/i18n/en/gen.php b/app/i18n/en/gen.php index 9c6bd5070..214b24474 100644 --- a/app/i18n/en/gen.php +++ b/app/i18n/en/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => 'No labels', 'new_article' => 'There are new articles available, click to refresh the page.', 'should_be_activated' => 'JavaScript must be enabled', + 'unsafe_csp_header' => 'The CSP header in use is unsafe and FreshRSS may be vulnerable to XSS attacks. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">See documentation</a>', ), 'lang' => array( 'cs' => 'Čeština', diff --git a/app/i18n/es/gen.php b/app/i18n/es/gen.php index ae606ad37..c563a1e9b 100644 --- a/app/i18n/es/gen.php +++ b/app/i18n/es/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => 'Sin etiquetas', 'new_article' => 'Hay nuevos artículos disponibles. Pincha para refrescar la página.', 'should_be_activated' => 'JavaScript debe estar activado', + 'unsafe_csp_header' => 'The CSP header in use is unsafe and FreshRSS may be vulnerable to XSS attacks. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">See documentation</a>', // TODO ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/i18n/fa/gen.php b/app/i18n/fa/gen.php index d9dda44d4..3168a3cb0 100644 --- a/app/i18n/fa/gen.php +++ b/app/i18n/fa/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => 'بدون برچسب', 'new_article' => 'مقالات جدیدی موجود است', 'should_be_activated' => ' جاوا اسکریپت باید فعال باشد', + 'unsafe_csp_header' => 'The CSP header in use is unsafe and FreshRSS may be vulnerable to XSS attacks. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">See documentation</a>', // TODO ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/i18n/fi/gen.php b/app/i18n/fi/gen.php index c74a3dd68..9171852f0 100644 --- a/app/i18n/fi/gen.php +++ b/app/i18n/fi/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => 'Ei tunnisteita', 'new_article' => 'Uusia artikkeleita on saatavilla. Päivitä sivu napsauttamalla.', 'should_be_activated' => 'JavaScriptin on oltava käytössä', + 'unsafe_csp_header' => 'The CSP header in use is unsafe and FreshRSS may be vulnerable to XSS attacks. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">See documentation</a>', // TODO ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/i18n/fr/gen.php b/app/i18n/fr/gen.php index 100910bbe..d9e8a5a67 100644 --- a/app/i18n/fr/gen.php +++ b/app/i18n/fr/gen.php @@ -152,9 +152,10 @@ return array( 'request_failed' => 'Une requête a échoué, cela peut être dû à des problèmes de connexion à Internet.', 'title_new_articles' => 'FreshRSS : nouveaux articles !', ), - 'labels_empty' => 'Pas d’étiquettes', // DIRTY + 'labels_empty' => 'Pas d’étiquettes', 'new_article' => 'Il y a de nouveaux articles disponibles, cliquez pour rafraîchir la page.', 'should_be_activated' => 'Le JavaScript doit être activé.', + 'unsafe_csp_header' => 'L’en-tête CSP utilisé n’est pas sécurisé et FreshRSS peut être vulnérable aux attaques XSS. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">Voir la documentation</a>', ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/i18n/he/gen.php b/app/i18n/he/gen.php index 5bdfad088..c2e7a4888 100644 --- a/app/i18n/he/gen.php +++ b/app/i18n/he/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => 'No labels', // TODO 'new_article' => 'מאמרים חדשים זמינים, לחצו לרענון העמוד.', 'should_be_activated' => 'חובה להפעיל JavaScript', + 'unsafe_csp_header' => 'The CSP header in use is unsafe and FreshRSS may be vulnerable to XSS attacks. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">See documentation</a>', // TODO ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/i18n/hu/gen.php b/app/i18n/hu/gen.php index 8ccc9441e..016f8742f 100644 --- a/app/i18n/hu/gen.php +++ b/app/i18n/hu/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => 'Nincsenek címkék', 'new_article' => 'Új cikkek elérhetőek, kattints a lap frissítéséhez.', 'should_be_activated' => 'A JavaScript futtatásának engedélyezve kell lennie', + 'unsafe_csp_header' => 'The CSP header in use is unsafe and FreshRSS may be vulnerable to XSS attacks. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">See documentation</a>', // TODO ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/i18n/id/gen.php b/app/i18n/id/gen.php index 1a331df2c..d81a12bf4 100644 --- a/app/i18n/id/gen.php +++ b/app/i18n/id/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => 'Tidak ada label', 'new_article' => 'Tidak ada artikel baru yang tersedia, klik untuk menyegarkan halaman.', 'should_be_activated' => 'JavaScript harus diaktifkan', + 'unsafe_csp_header' => 'The CSP header in use is unsafe and FreshRSS may be vulnerable to XSS attacks. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">See documentation</a>', // TODO ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/i18n/it/gen.php b/app/i18n/it/gen.php index f6c4ff621..46973c02a 100644 --- a/app/i18n/it/gen.php +++ b/app/i18n/it/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => 'Nessun tag', 'new_article' => 'Sono disponibili nuovi articoli, clicca qui per caricarli.', 'should_be_activated' => 'JavaScript deve essere abilitato', + 'unsafe_csp_header' => 'The CSP header in use is unsafe and FreshRSS may be vulnerable to XSS attacks. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">See documentation</a>', // TODO ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/i18n/ja/gen.php b/app/i18n/ja/gen.php index 02de4ac2a..56e649159 100644 --- a/app/i18n/ja/gen.php +++ b/app/i18n/ja/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => 'ラベルがありません', 'new_article' => '新しい記事があるのでクリックしてページをリフレッシュしてください。', 'should_be_activated' => 'JavaScriptは有効になっている必要があります。', + 'unsafe_csp_header' => 'The CSP header in use is unsafe and FreshRSS may be vulnerable to XSS attacks. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">See documentation</a>', // TODO ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/i18n/ko/gen.php b/app/i18n/ko/gen.php index 9d4a4a82d..f722c61f8 100644 --- a/app/i18n/ko/gen.php +++ b/app/i18n/ko/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => '라벨 없음', 'new_article' => '새 글이 있습니다. 여기를 클릭하면 페이지를 다시 불러옵니다.', 'should_be_activated' => '자바스크립트를 사용하도록 설정해야합니다', + 'unsafe_csp_header' => 'The CSP header in use is unsafe and FreshRSS may be vulnerable to XSS attacks. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">See documentation</a>', // TODO ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/i18n/lv/gen.php b/app/i18n/lv/gen.php index 1544e3834..54e12fe68 100644 --- a/app/i18n/lv/gen.php +++ b/app/i18n/lv/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => 'No labels', // TODO 'new_article' => 'Ir pieejami jauni raksti, noklikšķiniet, lai atsvaidzinātu lapu..', 'should_be_activated' => 'JavaScript jābūt ieslēgtam', + 'unsafe_csp_header' => 'The CSP header in use is unsafe and FreshRSS may be vulnerable to XSS attacks. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">See documentation</a>', // TODO ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/i18n/nl/gen.php b/app/i18n/nl/gen.php index 70b9cfd27..a031ed112 100644 --- a/app/i18n/nl/gen.php +++ b/app/i18n/nl/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => 'Geen labels', 'new_article' => 'Er zijn nieuwe artikelen beschikbaar. Klik om de pagina te vernieuwen.', 'should_be_activated' => 'JavaScript moet aanstaan', + 'unsafe_csp_header' => 'The CSP header in use is unsafe and FreshRSS may be vulnerable to XSS attacks. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">See documentation</a>', // TODO ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/i18n/oc/gen.php b/app/i18n/oc/gen.php index 14146c291..9a45c356e 100644 --- a/app/i18n/oc/gen.php +++ b/app/i18n/oc/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => 'No labels', // TODO 'new_article' => 'I a d’articles nòus disponibles, clicatz per actualizar la pagina.', 'should_be_activated' => 'JavaScript deu èsser activat', + 'unsafe_csp_header' => 'The CSP header in use is unsafe and FreshRSS may be vulnerable to XSS attacks. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">See documentation</a>', // TODO ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/i18n/pl/gen.php b/app/i18n/pl/gen.php index 249ac54b7..4dad4e799 100644 --- a/app/i18n/pl/gen.php +++ b/app/i18n/pl/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => 'Brak tagów', 'new_article' => 'Dostępne są nowe wiadomości. Kliknij, aby odświeżyć stronę.', 'should_be_activated' => 'JavaScript musi być włączony', + 'unsafe_csp_header' => 'Używany nagłówek CSP jest niebezpieczny i FreshRSS może być podatny na ataki XSS. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">Zobacz dokumentację</a>', ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/i18n/pt-br/gen.php b/app/i18n/pt-br/gen.php index 0e7ebf851..95cecc26c 100644 --- a/app/i18n/pt-br/gen.php +++ b/app/i18n/pt-br/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => 'No labels', // TODO 'new_article' => 'Há novos artigos disponíveis, clique para atualizar a página.', 'should_be_activated' => 'O JavaScript precisa estar ativo', + 'unsafe_csp_header' => 'The CSP header in use is unsafe and FreshRSS may be vulnerable to XSS attacks. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">See documentation</a>', // TODO ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/i18n/pt-pt/gen.php b/app/i18n/pt-pt/gen.php index 7dabdc800..a7ca5d56b 100644 --- a/app/i18n/pt-pt/gen.php +++ b/app/i18n/pt-pt/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => 'No labels', // TODO 'new_article' => 'Há novos artigos disponíveis, clique para atualizar a página.', 'should_be_activated' => 'O JavaScript precisa estar ativo', + 'unsafe_csp_header' => 'The CSP header in use is unsafe and FreshRSS may be vulnerable to XSS attacks. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">See documentation</a>', // TODO ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/i18n/ru/gen.php b/app/i18n/ru/gen.php index 3d367e43e..b5c4cfa17 100644 --- a/app/i18n/ru/gen.php +++ b/app/i18n/ru/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => 'Нет меток', 'new_article' => 'Появились новые статьи. Нажмите, чтобы обновить страницу.', 'should_be_activated' => 'JavaScript должен быть включён', + 'unsafe_csp_header' => 'The CSP header in use is unsafe and FreshRSS may be vulnerable to XSS attacks. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">See documentation</a>', // TODO ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/i18n/sk/gen.php b/app/i18n/sk/gen.php index 611ff5918..6f53de79f 100644 --- a/app/i18n/sk/gen.php +++ b/app/i18n/sk/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => 'Žiadne štítky', 'new_article' => 'Našli sa nové články. Kliknite na obnovenie stránky.', 'should_be_activated' => 'Musíte povoliť JavaScript', + 'unsafe_csp_header' => 'The CSP header in use is unsafe and FreshRSS may be vulnerable to XSS attacks. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">See documentation</a>', // TODO ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/i18n/tr/gen.php b/app/i18n/tr/gen.php index e6d96c532..50f75ad74 100644 --- a/app/i18n/tr/gen.php +++ b/app/i18n/tr/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => 'Etiket yok', 'new_article' => 'Yeni makaleler mevcut, sayfayı yenilemek için tıklayın.', 'should_be_activated' => 'JavaScript etkinleştirilmiş olmalı', + 'unsafe_csp_header' => 'The CSP header in use is unsafe and FreshRSS may be vulnerable to XSS attacks. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">See documentation</a>', // TODO ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/i18n/zh-cn/gen.php b/app/i18n/zh-cn/gen.php index 91b38d9e0..cb4be6b7e 100644 --- a/app/i18n/zh-cn/gen.php +++ b/app/i18n/zh-cn/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => '无标签', 'new_article' => '发现新文章,点击刷新页面。', 'should_be_activated' => '必须启用 JavaScript', + 'unsafe_csp_header' => 'The CSP header in use is unsafe and FreshRSS may be vulnerable to XSS attacks. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">See documentation</a>', // TODO ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/i18n/zh-tw/gen.php b/app/i18n/zh-tw/gen.php index ed36c6cbc..420ecd61c 100644 --- a/app/i18n/zh-tw/gen.php +++ b/app/i18n/zh-tw/gen.php @@ -155,6 +155,7 @@ return array( 'labels_empty' => '沒有標籤', 'new_article' => '發現新文章,點擊刷新頁面。', 'should_be_activated' => '必須啟用 JavaScript', + 'unsafe_csp_header' => 'The CSP header in use is unsafe and FreshRSS may be vulnerable to XSS attacks. <a target="_blank" href="https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security">See documentation</a>', // TODO ), 'lang' => array( 'cs' => 'Čeština', // IGNORE diff --git a/app/views/helpers/javascript_vars.phtml b/app/views/helpers/javascript_vars.phtml index 831c67f89..a7564af67 100644 --- a/app/views/helpers/javascript_vars.phtml +++ b/app/views/helpers/javascript_vars.phtml @@ -7,6 +7,8 @@ $extData = Minz_ExtensionManager::callHook('js_vars', []); echo json_encode([ 'context' => [ 'anonymous' => !FreshRSS_Auth::hasAccess(), + 'admin' => FreshRSS_Auth::hasAccess('admin'), + 'suppress_csp_warning' => FreshRSS_Context::systemConf()->suppress_csp_warning, 'auto_remove_article' => !!FreshRSS_Context::isAutoRemoveAvailable(), 'hide_posts' => !(FreshRSS_Context::userConf()->display_posts || Minz_Request::actionName() === 'reader'), 'display_order' => Minz_Request::paramString('order') ?: FreshRSS_Context::userConf()->sort_order, @@ -77,6 +79,7 @@ echo json_encode([ 'labels_empty' => _t('gen.js.labels_empty'), 'favicon_size_exceeded' => _t('feedback.sub.feed.favicon.too_large', format_bytes(FreshRSS_Context::systemConf()->limits['max_favicon_upload_size'])), 'language' => FreshRSS_Context::userConf()->language, + 'unsafe_csp_header' => _t('gen.js.unsafe_csp_header'), ], 'icons' => [ 'read' => rawurlencode(_i('read')), diff --git a/config.default.php b/config.default.php index c839c9a3c..91eca5597 100644 --- a/config.default.php +++ b/config.default.php @@ -83,6 +83,11 @@ return [ # https://example.net/FreshRSS/p/i/?c=auth&a=login&u=alice&p=1234 'unsafe_autologin_enabled' => false, + # By default, FreshRSS will display a warning to logged-in admin users if the CSP policy is insecure. + # This setting can disable the warning. + # For more information see: https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html#security + 'suppress_csp_warning' => false, + # Enable or not the use of syslog to log the activity of # SimplePie, which is retrieving RSS feeds via HTTP requests. 'simplepie_syslog_enabled' => true, diff --git a/docs/en/admins/10_ServerConfig.md b/docs/en/admins/10_ServerConfig.md index 07ea147b6..54f4f0fb4 100644 --- a/docs/en/admins/10_ServerConfig.md +++ b/docs/en/admins/10_ServerConfig.md @@ -112,3 +112,21 @@ server { } } ``` + +## Security + +Avoid overwriting the [`Content-Security-Policy`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP) header with directives such as `more_set_headers "Content-Security-Policy: ..."` +This will likely make your FreshRSS instance vulnerable to event handler XSS attacks, since FreshRSS does not yet blacklist all event attributes. + +✅ Example of good CSP: `default-src 'self' frame-ancestors 'self'` +❌ Bad CSP: `upgrade-insecure-requests` + +Debug CSP header: +* With DevTools network tab: press F12 +* [CSP Evaluator](https://csp-evaluator.withgoogle.com/) + +If you're aware of the risks and want to ignore the warning shown to admin users, change the `suppress_csp_warning` setting to `true` in `./data/config.php` + +Note that FreshRSS already ships with a secure CSP configuration, therefore it's not necessary to make any adjustments to CSP unless you're writing an extension. + +For that, look into the [`Minz_ActionController::_csp`](https://github.com/FreshRSS/FreshRSS/blob/d9197d7e32a97f29829ffd4cf4371b1853e51fa2/lib/Minz/ActionController.php#L76-L96) function and use it in individual actions. diff --git a/docs/i18n/flags/gen/cs.svg b/docs/i18n/flags/gen/cs.svg index b997fd620..dba66087d 100644 --- a/docs/i18n/flags/gen/cs.svg +++ b/docs/i18n/flags/gen/cs.svg @@ -1,7 +1,7 @@ <!-- This file is automatically generated by `cli/check.translation.php -g` --> <svg xmlns="http://www.w3.org/2000/svg" width="70" height="20"> <g fill="white" font-size="12" font-family="Verdana" text-anchor="middle"> - <rect rx="3" width="70" height="20" fill="green" /> - <text x="34" y="14">🇨🇿 90%</text> + <rect rx="3" width="70" height="20" fill="gold" /> + <text x="34" y="14">🇨🇿 89%</text> </g> </svg>
\ No newline at end of file diff --git a/docs/i18n/flags/gen/ja.svg b/docs/i18n/flags/gen/ja.svg index 82d7b683c..e14f6bd58 100644 --- a/docs/i18n/flags/gen/ja.svg +++ b/docs/i18n/flags/gen/ja.svg @@ -2,6 +2,6 @@ <svg xmlns="http://www.w3.org/2000/svg" width="70" height="20"> <g fill="white" font-size="12" font-family="Verdana" text-anchor="middle"> <rect rx="3" width="70" height="20" fill="green" /> - <text x="34" y="14">🇯🇵 97%</text> + <text x="34" y="14">🇯🇵 96%</text> </g> </svg>
\ No newline at end of file diff --git a/docs/i18n/flags/gen/ko.svg b/docs/i18n/flags/gen/ko.svg index 7ad71b132..bde6a488c 100644 --- a/docs/i18n/flags/gen/ko.svg +++ b/docs/i18n/flags/gen/ko.svg @@ -1,7 +1,7 @@ <!-- This file is automatically generated by `cli/check.translation.php -g` --> <svg xmlns="http://www.w3.org/2000/svg" width="70" height="20"> <g fill="white" font-size="12" font-family="Verdana" text-anchor="middle"> - <rect rx="3" width="70" height="20" fill="green" /> - <text x="34" y="14">🇰🇷 90%</text> + <rect rx="3" width="70" height="20" fill="gold" /> + <text x="34" y="14">🇰🇷 89%</text> </g> </svg>
\ No newline at end of file diff --git a/docs/i18n/flags/gen/ru.svg b/docs/i18n/flags/gen/ru.svg index b7b471ce1..01426a5df 100644 --- a/docs/i18n/flags/gen/ru.svg +++ b/docs/i18n/flags/gen/ru.svg @@ -1,7 +1,7 @@ <!-- This file is automatically generated by `cli/check.translation.php -g` --> <svg xmlns="http://www.w3.org/2000/svg" width="70" height="20"> <g fill="white" font-size="12" font-family="Verdana" text-anchor="middle"> - <rect rx="3" width="70" height="20" fill="green" /> - <text x="34" y="14">🇷🇺 90%</text> + <rect rx="3" width="70" height="20" fill="gold" /> + <text x="34" y="14">🇷🇺 89%</text> </g> </svg>
\ No newline at end of file diff --git a/docs/i18n/flags/gen/zh-cn.svg b/docs/i18n/flags/gen/zh-cn.svg index 27e539722..41339b5f6 100644 --- a/docs/i18n/flags/gen/zh-cn.svg +++ b/docs/i18n/flags/gen/zh-cn.svg @@ -1,7 +1,7 @@ <!-- This file is automatically generated by `cli/check.translation.php -g` --> <svg xmlns="http://www.w3.org/2000/svg" width="70" height="20"> <g fill="white" font-size="12" font-family="Verdana" text-anchor="middle"> - <rect rx="3" width="70" height="20" fill="green" /> - <text x="34" y="14">🇨🇳 90%</text> + <rect rx="3" width="70" height="20" fill="gold" /> + <text x="34" y="14">🇨🇳 89%</text> </g> </svg>
\ No newline at end of file diff --git a/docs/i18n/flags/gen/zh-tw.svg b/docs/i18n/flags/gen/zh-tw.svg index 66ddcb170..18374e310 100644 --- a/docs/i18n/flags/gen/zh-tw.svg +++ b/docs/i18n/flags/gen/zh-tw.svg @@ -1,7 +1,7 @@ <!-- This file is automatically generated by `cli/check.translation.php -g` --> <svg xmlns="http://www.w3.org/2000/svg" width="70" height="20"> <g fill="white" font-size="12" font-family="Verdana" text-anchor="middle"> - <rect rx="3" width="70" height="20" fill="green" /> - <text x="34" y="14">🇹🇼 90%</text> + <rect rx="3" width="70" height="20" fill="gold" /> + <text x="34" y="14">🇹🇼 89%</text> </g> </svg>
\ No newline at end of file diff --git a/lib/Minz/ActionController.php b/lib/Minz/ActionController.php index 80ce8386f..9549a146f 100644 --- a/lib/Minz/ActionController.php +++ b/lib/Minz/ActionController.php @@ -76,16 +76,17 @@ abstract class Minz_ActionController { /** * Set CSP policies. * - * A default-src directive should always be given. + * default-src and frame-ancestors directives should always be given. * * References: - * - https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP - * - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/default-src + * - https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP + * - https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/default-src + * - https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/frame-ancestors * * @param array<string,string> $policies An array where keys are directives and values are sources. */ protected function _csp(array $policies): void { - if (!isset($policies['default-src'])) { + if (!isset($policies['default-src']) || !isset($policies['frame-ancestors'])) { $action = Minz_Request::controllerName() . '#' . Minz_Request::actionName(); Minz_Log::warning( "Default CSP policy is not declared for action {$action}.", diff --git a/p/scripts/main.js b/p/scripts/main.js index 1e35c84fa..c9f856c73 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -2181,6 +2181,26 @@ function init_normal() { }); } +function init_csp_alert() { + if (!context.admin || context.suppress_csp_warning) { + return; + } + + try { + // eslint-disable-next-line no-new-func + Function(); + } catch (_) { + // Exit if 'script-src' is set and 'unsafe-eval' isn't set in CSP + return; + } + + document.body.insertAdjacentHTML('afterbegin', ` + <div class="alert alert-error"> + <span>${context.i18n.unsafe_csp_header}</span> + </div> + `); +} + function init_main_beforeDOM() { history.scrollRestoration = 'manual'; document.scrollingElement.scrollTop = 0; @@ -2193,6 +2213,7 @@ function init_main_beforeDOM() { function init_main_afterDOM() { removeFirstLoadSpinner(); init_notifications(); + init_csp_alert(); init_confirm_action(); const stream = document.getElementById('stream'); if (stream) { |
