fix(docker): escape container status commands

Build container status commands with escaped container names in the
Docker helper so callers can pass raw identifiers consistently.
This commit is contained in:
Andras Bacsai committed 2026-07-07 18:00:40 +02:00
1 parent a165e03d06
commit 9f13434273
3 files changed
+22 -10

No files matched your search

@@ -455,9 +455,8 @@ class ServiceApplicationsController extends Controller
} }
$containerName = $serviceApplication->name.'-'.$serviceApplication->service->uuid; $containerName = $serviceApplication->name.'-'.$serviceApplication->service->uuid;
$safeContainerName = escapeshellarg($containerName);
$status = getContainerStatus($server, $safeContainerName); $status = getContainerStatus($server, $containerName);
if ($status !== 'running') { if ($status !== 'running') {
return response()->json([ return response()->json([
'message' => 'Service application container is not running.', 'message' => 'Service application container is not running.',
+9 -4
View File
@@ -178,13 +178,18 @@ function executeInDocker(string $containerId, string $command)
return "docker exec {$containerId} bash -c '{$escapedCommand}'"; return "docker exec {$containerId} bash -c '{$escapedCommand}'";
} }
function getContainerStatus(Server $server, string $container_id, bool $all_data = false, bool $throwError = false) function buildContainerStatusCommand(Server $server, string $container_id): string
{ {
if ($server->isSwarm()) { if ($server->isSwarm()) {
$container = instant_remote_process(["docker service ls --filter 'name={$container_id}' --format '{{json .}}' "], $server, $throwError); return 'docker service ls --filter '.escapeshellarg("name={$container_id}")." --format '{{json .}}' ";
} else {
$container = instant_remote_process(["docker inspect --format '{{json .}}' {$container_id}"], $server, $throwError);
} }
return "docker inspect --format '{{json .}}' ".escapeshellarg($container_id);
}
function getContainerStatus(Server $server, string $container_id, bool $all_data = false, bool $throwError = false)
{
$container = instant_remote_process([buildContainerStatusCommand($server, $container_id)], $server, $throwError);
if (! $container) { if (! $container) {
return 'exited'; return 'exited';
} }
@@ -1016,12 +1016,20 @@ describe('service application lifecycle command escaping', function () {
'stop action' => 'Actions/Service/StopServiceApplication.php', 'stop action' => 'Actions/Service/StopServiceApplication.php',
]); ]);
test('service application logs endpoint escapes container name before docker helpers', function () { test('docker status helper escapes container names', function () {
$source = file_get_contents(base_path('bootstrap/helpers/docker.php'));
expect($source)->toContain('function buildContainerStatusCommand')
->and($source)->toContain('escapeshellarg("name={$container_id}")')
->and($source)->toContain('escapeshellarg($container_id)');
});
test('service application logs endpoint passes raw container name to docker helpers', function () {
$source = file_get_contents(app_path('Http/Controllers/Api/ServiceApplicationsController.php')); $source = file_get_contents(app_path('Http/Controllers/Api/ServiceApplicationsController.php'));
expect($source)->toContain('$safeContainerName = escapeshellarg($containerName)') expect($source)->toContain('getContainerStatus($server, $containerName)')
->and($source)->toContain('getContainerStatus($server, $safeContainerName)') ->and($source)->toContain('getContainerLogs($server, $containerName, $lines)')
->and($source)->toContain('getContainerLogs($server, $containerName, $lines)'); ->and($source)->not->toContain('$safeContainerName = escapeshellarg($containerName)');
}); });
}); });