From 99e9b7ec56dc81f278beb2947182a7eccdf6d731 Mon Sep 17 00:00:00 2001 From: Max Berger Date: Wed, 18 Mar 2026 21:04:50 +0100 Subject: [PATCH 1/5] Add CSP to local web UI forbidding JavaScript eval() --- radicale/httputils.py | 5 ++++- radicale/web/internal_data/css/main.css | 6 ++++++ radicale/web/internal_data/index.html | 17 ++++++----------- radicale/web/internal_data/js/main.js | 9 +++++++-- radicale/web/internal_data/js/utils/misc.js | 11 +++++++++++ 5 files changed, 34 insertions(+), 14 deletions(-) diff --git a/radicale/httputils.py b/radicale/httputils.py index 1d9d08b6..ddad1eac 100644 --- a/radicale/httputils.py +++ b/radicale/httputils.py @@ -198,7 +198,10 @@ def _serve_traversable( return NOT_FOUND content_type = MIMETYPES.get( os.path.splitext(traversable.name)[1].lower(), FALLBACK_MIMETYPE) - headers = {"Content-Type": content_type} + headers = { + "Content-Type": content_type, + "Content-Security-Policy": "default-src 'self'; object-src 'none'" + } if isinstance(traversable, pathlib.Path): headers["Last-Modified"] = time.strftime( "%a, %d %b %Y %H:%M:%S GMT", diff --git a/radicale/web/internal_data/css/main.css b/radicale/web/internal_data/css/main.css index de3c9210..b06e2241 100644 --- a/radicale/web/internal_data/css/main.css +++ b/radicale/web/internal_data/css/main.css @@ -112,6 +112,7 @@ main { #logoutview span { width: calc(100% - 60px); display: inline-block; + word-wrap: break-word; } #logoutview a { @@ -191,6 +192,7 @@ main { font-size: 1em; max-height: 130px; overflow: overlay; + word-wrap: break-word; } #collectionsscene article:hover ul { @@ -518,3 +520,7 @@ button.inline { margin: 0 2px; width: 1.4em; } + +.hidden { + display: none !important; +} diff --git a/radicale/web/internal_data/index.html b/radicale/web/internal_data/index.html index a21866b0..a6571212 100644 --- a/radicale/web/internal_data/index.html +++ b/radicale/web/internal_data/index.html @@ -14,17 +14,12 @@ Radicale Web Interface - @@ -86,8 +81,8 @@ Webcal - -

Description

+ +

Description