From 3b5980aaa969607a40efd6d3b3dd3b01d5629b7e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 6 Nov 2025 21:49:37 +0000 Subject: [PATCH 1/3] Initial plan From f789ee839150d958bb9979efafc5a713b379a1e4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 6 Nov 2025 21:53:01 +0000 Subject: [PATCH 2/3] Fix open redirect vulnerability in LoginController Co-authored-by: ljonesfl <1099983+ljonesfl@users.noreply.github.com> --- src/Cms/Controllers/Auth/LoginController.php | 36 ++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/Cms/Controllers/Auth/LoginController.php b/src/Cms/Controllers/Auth/LoginController.php index e755a10..2f99c00 100644 --- a/src/Cms/Controllers/Auth/LoginController.php +++ b/src/Cms/Controllers/Auth/LoginController.php @@ -44,6 +44,30 @@ public function __construct( ?Application $app = null ) $this->_CsrfManager = new CsrfTokenManager( $this->_SessionManager ); } + /** + * Validate redirect URL to prevent open redirect vulnerabilities + * + * @param string $url The URL to validate + * @return bool True if the URL is safe to use + */ + private function isValidRedirectUrl( string $url ): bool + { + // Only allow relative URLs or same-origin absolute URLs + if( empty( $url ) ) + { + return false; + } + + // Reject URLs with schemes (http://, https://, javascript:, etc.) + if( preg_match( '#^[a-z][a-z0-9+.-]*:#i', $url ) ) + { + return false; + } + + // Must start with / for internal path + return str_starts_with( $url, '/' ); + } + /** * Show login form */ @@ -56,13 +80,18 @@ public function showLoginForm( array $Parameters ): string exit; } + $requestedRedirect = $_GET['redirect'] ?? '/admin/dashboard'; + $redirectUrl = $this->isValidRedirectUrl( $requestedRedirect ) + ? $requestedRedirect + : '/admin/dashboard'; + $ViewData = [ 'Title' => 'Login | ' . $this->getName(), 'Description' => 'Login to ' . $this->getName(), 'CsrfToken' => $this->_CsrfManager->getToken(), 'Error' => $this->_SessionManager->getFlash( 'error' ), 'Success' => $this->_SessionManager->getFlash( 'success' ), - 'RedirectUrl' => $_GET['redirect'] ?? '/admin/dashboard' + 'RedirectUrl' => $redirectUrl ]; return $this->renderHtml( @@ -112,7 +141,10 @@ public function login( array $Parameters ): string $this->_SessionManager->flash( 'success', 'Welcome back!' ); // Redirect to intended URL or dashboard - $RedirectUrl = $_POST['redirect_url'] ?? '/admin/dashboard'; + $requestedRedirect = $_POST['redirect_url'] ?? '/admin/dashboard'; + $RedirectUrl = $this->isValidRedirectUrl( $requestedRedirect ) + ? $requestedRedirect + : '/admin/dashboard'; header( 'Location: ' . $RedirectUrl ); exit; } From 087f6bbe076f3182530290eeffd5315e6c320eac Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 6 Nov 2025 21:54:06 +0000 Subject: [PATCH 3/3] Add protection against protocol-relative URLs Co-authored-by: ljonesfl <1099983+ljonesfl@users.noreply.github.com> --- src/Cms/Controllers/Auth/LoginController.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Cms/Controllers/Auth/LoginController.php b/src/Cms/Controllers/Auth/LoginController.php index 2f99c00..9f0b9a2 100644 --- a/src/Cms/Controllers/Auth/LoginController.php +++ b/src/Cms/Controllers/Auth/LoginController.php @@ -64,6 +64,12 @@ private function isValidRedirectUrl( string $url ): bool return false; } + // Reject protocol-relative URLs (//example.com) + if( str_starts_with( $url, '//' ) ) + { + return false; + } + // Must start with / for internal path return str_starts_with( $url, '/' ); }