From f2ece40dd47e4ee9ba3e500648300535b18bd690 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Thu, 29 Oct 2026 18:29:51 +0100 Subject: [PATCH] fix(terminal): fall back to usable shell for nologin and false (#12242) Co-authored-by: Claude Opus 5.5 --- app/Services/TerminalSessionService.php | 3 ++- tests/Unit/TerminalShellCommandTest.php | 36 +++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 tests/Unit/TerminalShellCommandTest.php diff --git a/app/Services/TerminalSessionService.php b/app/Services/TerminalSessionService.php index b2fb4d09a2..b1f113ca7b 100644 --- a/app/Services/TerminalSessionService.php +++ b/app/Services/TerminalSessionService.php @@ -109,7 +109,8 @@ class TerminalSessionService { return 'PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin && '. 'if [ -f ~/.profile ]; then . ~/.profile; fi && '. - 'if [ -n "$SHELL" ] && [ -x "$SHELL" ]; then exec $SHELL; else sh; fi'; + 'if [ -n "$SHELL" ] && [ -x "$SHELL" ] && [ "${SHELL##*/}" != nologin ] && [ "${SHELL##*/}" != false ]; then exec $SHELL; '. + 'elif command -v bash >/dev/null 2>&1; then exec bash; else sh; fi'; } private function cacheKey(string $token): string diff --git a/tests/Unit/TerminalShellCommandTest.php b/tests/Unit/TerminalShellCommandTest.php new file mode 100644 index 0000000000..cba8103418 --- /dev/null +++ b/tests/Unit/TerminalShellCommandTest.php @@ -0,0 +1,36 @@ + $this->shellCommand())->call(new TerminalSessionService); + + $process = new Process(['sh', '-c', $command], null, ['HOME' => $home, 'SHELL' => $shell]); + $process->setInput("echo fallback-ran\n"); + $process->run(); + + return $process; +} + +it('falls back to a usable shell when $SHELL is a login-disabling shell', function (string $shellName) { + $process = runTerminalShellCommand($shellName); + + expect($process->getOutput())->toContain('fallback-ran') + ->not->toContain("{$shellName}-ran"); + expect($process->getExitCode())->toBe(0); +})->with(['nologin', 'false']); + +it('starts $SHELL when it is a usable shell', function () { + $process = runTerminalShellCommand('zsh', exitCode: 0); + + expect($process->getOutput())->toContain('zsh-ran'); + expect($process->getExitCode())->toBe(0); +});