diff --git a/.changes/restricted-preview-changes-rollbacks-and-repository.md b/.changes/restricted-preview-changes-rollbacks-and-repository.md index 0f29546f3b..f910912ae8 100644 --- a/.changes/restricted-preview-changes-rollbacks-and-repository.md +++ b/.changes/restricted-preview-changes-rollbacks-and-repository.md @@ -7,3 +7,4 @@ Restricted preview changes, rollbacks and repository URL changes - Opening a preview, changing its pull request URL, Git type or Docker tag, or choosing a commit through the API needs write access, a deploy token can only redeploy an existing preview - A rollback goes only to a listed rollback image or a successful production deployment - A new `git_repository` of an application is validated like in the UI +- The `docker_tag` of `/api/v1/deploy` is validated like in the preview API diff --git a/app/Http/Controllers/Api/DeployController.php b/app/Http/Controllers/Api/DeployController.php index 1fbea69088..589e838834 100644 --- a/app/Http/Controllers/Api/DeployController.php +++ b/app/Http/Controllers/Api/DeployController.php @@ -17,6 +17,7 @@ use App\Models\Service; use App\Models\Tag; use App\Services\Access\AccessResolver; use App\Support\ResourceStartActivity; +use App\Support\ValidationPatterns; use Illuminate\Auth\Access\AuthorizationException; use Illuminate\Http\Request; use OpenApi\Attributes as OA; @@ -405,6 +406,9 @@ class DeployController extends Controller if ($tags && $pr) { return response()->json(['message' => 'You can only use tag or pr, not both.'], 400); } + if (! ValidationPatterns::isValidDockerImageTag($dockerTag, allowVariables: false)) { + return response()->json(['message' => 'docker_tag must be a valid Docker tag: letters, digits, underscores, periods, and dashes, at most 128 characters.'], 400); + } if ($dockerTag && $pr === 0) { return response()->json(['message' => 'docker_tag requires pull_request_id.'], 400); } diff --git a/tests/Feature/DockerImagePreviewDeploymentApiTest.php b/tests/Feature/DockerImagePreviewDeploymentApiTest.php index b63b26634b..0857ddbee0 100644 --- a/tests/Feature/DockerImagePreviewDeploymentApiTest.php +++ b/tests/Feature/DockerImagePreviewDeploymentApiTest.php @@ -126,6 +126,20 @@ test('it rejects docker_tag without pull_request_id', function () { $response->assertJson(['message' => 'docker_tag requires pull_request_id.']); }); +test('it rejects a docker_tag that is not a valid docker tag', function (string $dockerTag) { + $application = createDockerImageApplication($this->environment, $this->destination); + + $this->withHeaders(['Authorization' => 'Bearer '.$this->bearerToken])->postJson('/api/v1/deploy', [ + 'uuid' => $application->uuid, + 'pull_request_id' => 5, + 'docker_tag' => $dockerTag, + ])->assertStatus(400) + ->assertJson(['message' => 'docker_tag must be a valid Docker tag: letters, digits, underscores, periods, and dashes, at most 128 characters.']); + + expect($application->previews()->count())->toBe(0) + ->and($application->deployment_queue()->count())->toBe(0); +})->with(['-leading-dash', 'a;id', '$TAG', 'a:b', str_repeat('a', 129)]); + test('it rejects docker_tag for non docker image applications', function () { $application = Application::factory()->create([ 'uuid' => (string) Str::uuid(),