From c1951726c0a9afbf81a10473de124ad8d12d7ed5 Mon Sep 17 00:00:00 2001 From: ShadowArcanist <162910371+ShadowArcanist@users.noreply.github.com> Date: Sat, 21 Feb 2026 21:42:28 +0530 Subject: [PATCH 1/5] feat(service): disable pterodactyl panel and pterodactyl wings The template is using latest version of pterodactyl and the issue is the db migration fails for new users but works fine for existing deployments. We cannot revert the template to previous version because the current latest version addresses few CVEs so it's better to disable this template for now --- templates/compose/pterodactyl-panel.yaml | 3 ++- templates/compose/pterodactyl-with-wings.yaml | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/templates/compose/pterodactyl-panel.yaml b/templates/compose/pterodactyl-panel.yaml index 9a3f6c779..c86d9d468 100644 --- a/templates/compose/pterodactyl-panel.yaml +++ b/templates/compose/pterodactyl-panel.yaml @@ -1,3 +1,4 @@ +# ignore: true # documentation: https://pterodactyl.io/ # slogan: Pterodactyl is a free, open-source game server management panel # category: media @@ -102,4 +103,4 @@ services: - MAIL_PORT=$MAIL_PORT - MAIL_USERNAME=$MAIL_USERNAME - MAIL_PASSWORD=$MAIL_PASSWORD - - MAIL_ENCRYPTION=$MAIL_ENCRYPTION + - MAIL_ENCRYPTION=$MAIL_ENCRYPTION \ No newline at end of file diff --git a/templates/compose/pterodactyl-with-wings.yaml b/templates/compose/pterodactyl-with-wings.yaml index 6e1e3614c..20465a139 100644 --- a/templates/compose/pterodactyl-with-wings.yaml +++ b/templates/compose/pterodactyl-with-wings.yaml @@ -1,3 +1,4 @@ +# ignore: true # documentation: https://pterodactyl.io/ # slogan: Pterodactyl is a free, open-source game server management panel # category: media From 76d3709163e7d1625d008a2881eb375234ab998a Mon Sep 17 00:00:00 2001 From: ShadowArcanist <162910371+ShadowArcanist@users.noreply.github.com> Date: Sat, 21 Feb 2026 23:17:23 +0530 Subject: [PATCH 2/5] feat(service): upgrade beszel and beszel-agent to v0.18 --- templates/compose/beszel-agent.yaml | 21 +++++++++++++++---- templates/compose/beszel.yaml | 32 +++++++++++++++++++++++------ 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/templates/compose/beszel-agent.yaml b/templates/compose/beszel-agent.yaml index a318f4702..5d0b4fecc 100644 --- a/templates/compose/beszel-agent.yaml +++ b/templates/compose/beszel-agent.yaml @@ -6,13 +6,26 @@ services: beszel-agent: - image: 'henrygd/beszel-agent:0.16.1' # Released on 14 Nov 2025 + image: 'henrygd/beszel-agent:0.18.4' # Released on 21 Feb 2026 + network_mode: host # Network stats graphs won't work if agent cannot access host system network stack environment: + # Required - LISTEN=/beszel_socket/beszel.sock - - HUB_URL=${HUB_URL?} - - 'TOKEN=${TOKEN?}' - - 'KEY=${KEY?}' + - HUB_URL=$SERVICE_URL_BESZEL + - TOKEN=${TOKEN} # From hub token settings + - KEY=${KEY} # SSH public key(s) from hub + # Optional + - DISABLE_SSH=${DISABLE_SSH:-false} # Disable SSH + - LOG_LEVEL=${LOG_LEVEL:-warn} # Logging level + - SKIP_GPU=${SKIP_GPU:-false} # Skip GPU monitoring + - SYSTEM_NAME=${SYSTEM_NAME} # Custom system name volumes: - beszel_agent_data:/var/lib/beszel-agent - beszel_socket:/beszel_socket - '/var/run/docker.sock:/var/run/docker.sock:ro' + healthcheck: + test: ['CMD', '/agent', 'health'] + interval: 60s + timeout: 20s + retries: 10 + start_period: 5s \ No newline at end of file diff --git a/templates/compose/beszel.yaml b/templates/compose/beszel.yaml index cba11e4bb..bc68c1825 100644 --- a/templates/compose/beszel.yaml +++ b/templates/compose/beszel.yaml @@ -9,21 +9,41 @@ # Add the public Key in "Key" env variable and token in the "Token" variable below (These are obtained from Beszel UI) services: beszel: - image: 'henrygd/beszel:0.16.1' # Released on 14 Nov 2025 + image: 'henrygd/beszel:0.18.4' # Released on 21 Feb 2026 environment: - SERVICE_URL_BESZEL_8090 + - CONTAINER_DETAILS=${CONTAINER_DETAILS:-true} + - SHARE_ALL_SYSTEMS=${SHARE_ALL_SYSTEMS:-false} volumes: - 'beszel_data:/beszel_data' - 'beszel_socket:/beszel_socket' + healthcheck: + test: ['CMD', '/beszel', 'health', '--url', 'http://localhost:8090'] + interval: 30s + timeout: 20s + retries: 10 + start_period: 5s beszel-agent: - image: 'henrygd/beszel-agent:0.16.1' # Released on 14 Nov 2025 + image: 'henrygd/beszel-agent:0.18.4' # Released on 21 Feb 2026 + network_mode: host # Network stats graphs won't work if agent cannot access host system network stack environment: + # Required - LISTEN=/beszel_socket/beszel.sock - - HUB_URL=http://beszel:8090 - - 'TOKEN=${TOKEN}' - - 'KEY=${KEY}' + - HUB_URL=$SERVICE_URL_BESZEL + - TOKEN=${TOKEN} # From hub token settings + - KEY=${KEY} # SSH public key(s) from hub + # Optional + - DISABLE_SSH=${DISABLE_SSH:-false} # Disable SSH + - LOG_LEVEL=${LOG_LEVEL:-warn} # Logging level + - SKIP_GPU=${SKIP_GPU:-false} # Skip GPU monitoring + - SYSTEM_NAME=${SYSTEM_NAME} # Custom system name volumes: - beszel_agent_data:/var/lib/beszel-agent - beszel_socket:/beszel_socket - '/var/run/docker.sock:/var/run/docker.sock:ro' - + healthcheck: + test: ['CMD', '/agent', 'health'] + interval: 60s + timeout: 20s + retries: 10 + start_period: 5s \ No newline at end of file From b36d67288b307fa95a644a78d4cf42844bc5d1b9 Mon Sep 17 00:00:00 2001 From: ShadowArcanist <162910371+ShadowArcanist@users.noreply.github.com> Date: Tue, 24 Feb 2026 02:34:35 +0530 Subject: [PATCH 3/5] feat(service): disable plane The latest version of plane v1.2.2 have security fixed but our template is using v1.0.0 which is 5 months behind the current latest. New version v1.2.2 doesn't work with our existing template so disabling it for now to prevent users from deploying a vulnerable version of plane --- templates/compose/plane.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/compose/plane.yaml b/templates/compose/plane.yaml index bc2fbd637..346b0c664 100644 --- a/templates/compose/plane.yaml +++ b/templates/compose/plane.yaml @@ -1,3 +1,4 @@ +# ignore: true # documentation: https://docs.plane.so/self-hosting/methods/docker-compose # slogan: The open source project management tool # category: productivity From 2986d7604e012133c927ece5efd3691d679e7069 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Tue, 24 Feb 2026 10:17:16 +0100 Subject: [PATCH 4/5] chore: prepare for PR --- .../Middleware/CheckForcePasswordReset.php | 2 +- bootstrap/helpers/subscriptions.php | 2 + resources/views/errors/419.blade.php | 10 +-- .../Feature/TwoFactorChallengeAccessTest.php | 65 +++++++++++++++++++ 4 files changed, 71 insertions(+), 8 deletions(-) create mode 100644 tests/Feature/TwoFactorChallengeAccessTest.php diff --git a/app/Http/Middleware/CheckForcePasswordReset.php b/app/Http/Middleware/CheckForcePasswordReset.php index 78b1f896c..c857cb836 100644 --- a/app/Http/Middleware/CheckForcePasswordReset.php +++ b/app/Http/Middleware/CheckForcePasswordReset.php @@ -25,7 +25,7 @@ public function handle(Request $request, Closure $next): Response } $force_password_reset = auth()->user()->force_password_reset; if ($force_password_reset) { - if ($request->routeIs('auth.force-password-reset') || $request->path() === 'force-password-reset' || $request->path() === 'livewire/update' || $request->path() === 'logout') { + if ($request->routeIs('auth.force-password-reset') || $request->path() === 'force-password-reset' || $request->path() === 'two-factor-challenge' || $request->path() === 'livewire/update' || $request->path() === 'logout') { return $next($request); } diff --git a/bootstrap/helpers/subscriptions.php b/bootstrap/helpers/subscriptions.php index 4b84fb7f6..709af854a 100644 --- a/bootstrap/helpers/subscriptions.php +++ b/bootstrap/helpers/subscriptions.php @@ -77,6 +77,7 @@ function allowedPathsForUnsubscribedAccounts() 'login', 'logout', 'force-password-reset', + 'two-factor-challenge', 'livewire/update', 'admin', ]; @@ -95,6 +96,7 @@ function allowedPathsForInvalidAccounts() 'logout', 'verify', 'force-password-reset', + 'two-factor-challenge', 'livewire/update', ]; } diff --git a/resources/views/errors/419.blade.php b/resources/views/errors/419.blade.php index e7cd3fc45..8569f4e22 100644 --- a/resources/views/errors/419.blade.php +++ b/resources/views/errors/419.blade.php @@ -3,15 +3,11 @@

419

This page is definitely old, not like you!

-

Sorry, we couldn't find the page you're looking - for. +

Your session has expired. Please log in again to continue.

- - Go back - - - Dashboard + + Back to Login Contact support diff --git a/tests/Feature/TwoFactorChallengeAccessTest.php b/tests/Feature/TwoFactorChallengeAccessTest.php new file mode 100644 index 000000000..2bd58d197 --- /dev/null +++ b/tests/Feature/TwoFactorChallengeAccessTest.php @@ -0,0 +1,65 @@ +user = User::factory()->create(); + $this->team = Team::factory()->personal()->create(); + $this->team->members()->attach($this->user->id, ['role' => 'owner']); + session(['currentTeam' => $this->team]); +}); + +it('allows unauthenticated access to two-factor-challenge page', function () { + $response = $this->get('/two-factor-challenge'); + + // Fortify returns a redirect to /login if there's no login.id in session, + // but the important thing is it does NOT return a 419 or 500 + expect($response->status())->toBeIn([200, 302]); +}); + +it('includes two-factor-challenge in allowed paths for unsubscribed accounts', function () { + $paths = allowedPathsForUnsubscribedAccounts(); + + expect($paths)->toContain('two-factor-challenge'); +}); + +it('includes two-factor-challenge in allowed paths for invalid accounts', function () { + $paths = allowedPathsForInvalidAccounts(); + + expect($paths)->toContain('two-factor-challenge'); +}); + +it('includes two-factor-challenge in allowed paths for boarding accounts', function () { + $paths = allowedPathsForBoardingAccounts(); + + expect($paths)->toContain('two-factor-challenge'); +}); + +it('does not redirect authenticated user with force_password_reset from two-factor-challenge', function () { + $this->user->update(['force_password_reset' => true]); + + $response = $this->actingAs($this->user)->get('/two-factor-challenge'); + + // Should NOT redirect to force-password-reset page + if ($response->isRedirect()) { + expect($response->headers->get('Location'))->not->toContain('force-password-reset'); + } +}); + +it('renders 419 error page with login link instead of previous url', function () { + $response = $this->get('/two-factor-challenge', [ + 'X-CSRF-TOKEN' => 'invalid-token', + ]); + + // The 419 page should exist and contain a link to /login + $view = view('errors.419')->render(); + + expect($view)->toContain('/login'); + expect($view)->toContain('Back to Login'); + expect($view)->toContain('This page is definitely old, not like you!'); + expect($view)->not->toContain('url()->previous()'); +}); From 448e922e6cd1a51722b391402d9d15d6e9fe2d90 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Tue, 24 Feb 2026 12:56:54 +0100 Subject: [PATCH 5/5] chore: prepare for PR --- resources/views/components/forms/input.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/components/forms/input.blade.php b/resources/views/components/forms/input.blade.php index a329664a2..cf72dfbe9 100644 --- a/resources/views/components/forms/input.blade.php +++ b/resources/views/components/forms/input.blade.php @@ -25,7 +25,7 @@ class="flex absolute inset-y-0 right-0 items-center pr-2 cursor-pointer dark:hov {{-- Eye-off icon (shown when password is visible) --}} -