fix(service-apps): harden updates and docker commands

Escape service application lifecycle command arguments for deploy, restart, stop, and log status checks.
Validate API update payloads from JSON/form data before applying allowed fields, preserving explicit boolean and null values.
Add coverage for service application API authorization, team isolation, validation, and command escaping.
This commit is contained in:
Andras Bacsai committed 2026-07-07 15:10:24 +02:00
1 parent 95a3c453d8
commit a165e03d06
9 files changed
+356 -233

No files matched your search

@@ -996,6 +996,35 @@ describe('API route middleware for deploy actions', function () {
});
});
describe('service application lifecycle command escaping', function () {
test('service application deploy action escapes docker command arguments', function () {
$source = file_get_contents(app_path('Actions/Service/DeployServiceApplication.php'));
expect($source)->toContain('escapeshellarg($workdir)')
->and($source)->toContain('escapeshellarg($composeFile)')
->and($source)->toContain('escapeshellarg($service->uuid)')
->and($source)->toContain('escapeshellarg($composeServiceName)')
->and($source)->toContain('escapeshellarg($service->destination->network)');
});
test('service application restart and stop actions escape container names', function (string $path) {
$source = file_get_contents(app_path($path));
expect($source)->toContain('escapeshellarg($serviceApplication->name');
})->with([
'restart action' => 'Actions/Service/RestartServiceApplication.php',
'stop action' => 'Actions/Service/StopServiceApplication.php',
]);
test('service application logs endpoint escapes container name before docker helpers', function () {
$source = file_get_contents(app_path('Http/Controllers/Api/ServiceApplicationsController.php'));
expect($source)->toContain('$safeContainerName = escapeshellarg($containerName)')
->and($source)->toContain('getContainerStatus($server, $safeContainerName)')
->and($source)->toContain('getContainerLogs($server, $containerName, $lines)');
});
});
describe('install/build/start command validation', function () {
test('rejects semicolon injection in install_command', function () {
$rules = sharedDataApplications();