fix(api): validate the docker tag of deploy requests

Use the same tag format check as the preview API.
This commit is contained in:
Andras Bacsai
2026-11-09 10:58:08 +01:00
parent 769bddb326
commit f4cbf63e76
3 changed files with 19 additions and 0 deletions
@@ -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
@@ -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);
}
@@ -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(),