From 3d322e2fe2879fb77a10cf9983e471cb15c1b229 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Mar 2026 11:39:40 +0000 Subject: [PATCH] Move security headers from Caddyfiles to PHP middleware - Add SecurityHeadersMiddleware that sets Content-Security-Policy, X-Content-Type-Options, X-Frame-Options, X-Permitted-Cross-Domain-Policies, X-DNS-Prefetch-Control, Referrer-Policy, and X-Robots-Tag on all responses - Register SecurityHeadersMiddleware in index.php - Add click-handlers.js for CSP-compliant event handling (data-confirm, data-stop-event-propagation) - Update toggle-dark-mode.js to attach click handler via addEventListener - Remove inline onclick from theme toggle button in layout.twig - Replace all inline onclick with data-confirm in containers.twig, community-containers.twig, and optional-containers.twig Co-authored-by: szaimen <42591237+szaimen@users.noreply.github.com> Agent-Logs-Url: https://github.com/nextcloud/all-in-one/sessions/d87889ba-d2ad-4d76-b257-2afd725dac28 --- php/public/click-handlers.js | 15 ++++++++++++ php/public/index.php | 3 +++ php/public/toggle-dark-mode.js | 5 +++- .../Middleware/SecurityHeadersMiddleware.php | 23 +++++++++++++++++++ php/templates/containers.twig | 19 +++++++-------- .../includes/community-containers.twig | 2 +- .../includes/optional-containers.twig | 4 ++-- php/templates/layout.twig | 2 +- 8 files changed, 59 insertions(+), 14 deletions(-) create mode 100644 php/public/click-handlers.js create mode 100644 php/src/Middleware/SecurityHeadersMiddleware.php diff --git a/php/public/click-handlers.js b/php/public/click-handlers.js new file mode 100644 index 00000000..e757c9ce --- /dev/null +++ b/php/public/click-handlers.js @@ -0,0 +1,15 @@ +document.addEventListener("DOMContentLoaded", () => { + document.querySelectorAll('input[data-confirm]').forEach((element) => { + element.addEventListener('click', (event) => { + if (!confirm(element.dataset.confirm)) { + event.preventDefault(); + } + }); + }); + + document.querySelectorAll('[data-stop-event-propagation="true"]').forEach((element) => { + element.addEventListener('click', (event) => { + event.stopPropagation(); + }); + }); +}); diff --git a/php/public/index.php b/php/public/index.php index fb4f6117..aa5b3c67 100644 --- a/php/public/index.php +++ b/php/public/index.php @@ -55,6 +55,9 @@ $twig->addExtension(new \AIO\Twig\CsrfExtension($container->get(Guard::class))); // Auth Middleware $app->add(new \AIO\Middleware\AuthMiddleware($container->get(\AIO\Auth\AuthManager::class))); +// Security Headers Middleware +$app->add(new \AIO\Middleware\SecurityHeadersMiddleware()); + // API $app->post('/api/docker/watchtower', AIO\Controller\DockerController::class . ':StartWatchtowerContainer'); $app->get('/api/docker/getwatchtower', AIO\Controller\DockerController::class . ':StartWatchtowerContainer'); diff --git a/php/public/toggle-dark-mode.js b/php/public/toggle-dark-mode.js index 8eeba013..cdd9893d 100644 --- a/php/public/toggle-dark-mode.js +++ b/php/public/toggle-dark-mode.js @@ -32,4 +32,7 @@ function setThemeIcon(theme) { setThemeToDOM(getSavedTheme()); // Apply theme when the page loads -document.addEventListener('DOMContentLoaded', () => setThemeIcon(getSavedTheme())); +document.addEventListener('DOMContentLoaded', () => { + setThemeIcon(getSavedTheme()) + document.querySelector('button#theme-toggle')?.addEventListener('click', toggleTheme); +}); diff --git a/php/src/Middleware/SecurityHeadersMiddleware.php b/php/src/Middleware/SecurityHeadersMiddleware.php new file mode 100644 index 00000000..b1e020ce --- /dev/null +++ b/php/src/Middleware/SecurityHeadersMiddleware.php @@ -0,0 +1,23 @@ +handle($request); + return $response + ->withHeader('Content-Security-Policy', "default-src 'self'; base-uri 'self'; worker-src 'none'; object-src 'none'; upgrade-insecure-requests;") + ->withHeader('X-Content-Type-Options', 'nosniff') + ->withHeader('X-Frame-Options', 'DENY') + ->withHeader('X-Permitted-Cross-Domain-Policies', 'none') + ->withHeader('X-DNS-Prefetch-Control', 'off') + ->withHeader('Referrer-Policy', 'no-referrer') + ->withHeader('X-Robots-Tag', 'noindex, nofollow'); + } +} diff --git a/php/templates/containers.twig b/php/templates/containers.twig index 4aa6c48f..a68ed9e3 100644 --- a/php/templates/containers.twig +++ b/php/templates/containers.twig @@ -28,6 +28,7 @@ {# js for optional containers and additional containers forms #} + {% set hasBackupLocation = borg_backup_host_location or borg_remote_repo %} {% set isAnyRunning = false %} @@ -153,7 +154,7 @@
{% endif %} @@ -178,7 +179,7 @@ {% endfor %}You need to make sure that the timezone that you enter is valid. An example is Europe/Berlin. You can get valid values by looking at the 'TZ identifier' column of this list: click here. The default is Etc/UTC if nothing is entered.
{% else %} diff --git a/php/templates/includes/community-containers.twig b/php/templates/includes/community-containers.twig index 66cceb2b..da1dd26d 100644 --- a/php/templates/includes/community-containers.twig +++ b/php/templates/includes/community-containers.twig @@ -37,6 +37,6 @@ {% endfor %} - + diff --git a/php/templates/includes/optional-containers.twig b/php/templates/includes/optional-containers.twig index 980d8d0b..785cefe2 100644 --- a/php/templates/includes/optional-containers.twig +++ b/php/templates/includes/optional-containers.twig @@ -41,7 +41,7 @@