From 7c21c330c9d56efc486fbd5b9626c25127a5de48 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Mon, 28 Sep 2026 14:06:14 +0200 Subject: [PATCH] fix(gitlab): check the private key before using it for git commands Co-Authored-By: Claude Opus 5.5 --- app/Models/Application.php | 4 +-- bootstrap/helpers/gitlab.php | 8 ++++++ tests/Unit/GitlabSourceCommandsTest.php | 35 +++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/app/Models/Application.php b/app/Models/Application.php index d5da496ffb..5d3dd8bb2c 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -1608,7 +1608,7 @@ class Application extends BaseModel ]; } - $private_key = data_get($gitlabSource, 'privateKey.private_key'); + $private_key = gitlabAppPrivateKey($gitlabSource)?->private_key; if ($private_key) { $fullRepoUrl = $customRepository; @@ -1910,7 +1910,7 @@ class Application extends BaseModel ]; } - $private_key = data_get($gitlabSource, 'privateKey.private_key'); + $private_key = gitlabAppPrivateKey($gitlabSource)?->private_key; if ($private_key) { $fullRepoUrl = $customRepository; diff --git a/bootstrap/helpers/gitlab.php b/bootstrap/helpers/gitlab.php index 0ee44f2157..c40b39cb99 100644 --- a/bootstrap/helpers/gitlab.php +++ b/bootstrap/helpers/gitlab.php @@ -1,6 +1,7 @@ privateKey; + + return $privateKey?->team_id === $source->team_id ? $privateKey : null; +} + function generateGitlabCloneToken(GitlabApp $source): string { refreshGitlabToken($source); diff --git a/tests/Unit/GitlabSourceCommandsTest.php b/tests/Unit/GitlabSourceCommandsTest.php index e27236a8fe..320eaa388f 100644 --- a/tests/Unit/GitlabSourceCommandsTest.php +++ b/tests/Unit/GitlabSourceCommandsTest.php @@ -213,3 +213,38 @@ it('applies OAuth git config to GitLab merge-request fetch and submodule checkou ->toContain("http.version=HTTP/1.1 fetch origin 'merge-requests/2/head:pr-2-coolify'") ->toContain('http.version=HTTP/1.1 submodule update --init --recursive'); }); + +it('uses a GitLab source private key only when it belongs to the source team', function (int $keyTeamId, bool $expectKey) { + $privateKey = new PrivateKey; + $privateKey->forceFill(['team_id' => $keyTeamId, 'private_key' => 'fake-private-key']); + + $gitlabSource = new GitlabApp(['html_url' => 'https://gitlab.com', 'custom_port' => 22]); + $gitlabSource->forceFill(['team_id' => 1]); + $gitlabSource->setRelation('privateKey', $privateKey); + + $application = Mockery::mock(Application::class)->makePartial(); + $application->git_branch = 'main'; + $application->shouldReceive('deploymentType')->andReturn('source'); + $application->shouldReceive('customRepository')->andReturn([ + 'repository' => 'git@gitlab.com:user/repo.git', + 'port' => 22, + ]); + $application->shouldReceive('getAttribute')->with('source')->andReturn($gitlabSource); + $application->shouldReceive('getAttribute')->with('settings')->andReturn((object) [ + 'is_git_shallow_clone_enabled' => false, + 'is_git_submodules_enabled' => false, + ]); + $application->source = $gitlabSource; + + $lsRemote = $application->generateGitLsRemoteCommands('test-deployment-uuid', false)['commands']; + $import = $application->generateGitImportCommands(deployment_uuid: 'test-deployment-uuid', exec_in_docker: false)['commands']; + + foreach ([$lsRemote, $import] as $commands) { + $expectKey + ? expectGitlabCommandListToContain($commands, 'id_rsa_coolify_') + : expectGitlabCommandListNotToContain($commands, 'id_rsa_coolify_'); + } +})->with([ + 'same team' => [1, true], + 'other team' => [2, false], +]);