Skip to content

CVE-2026-34594: Verified Reproduction

CVE-2026-34594: Coolify authenticated command injection in Destination Network Management

CVE-2026-34594 is verified against the affected target. Vulnerability class: Command Injection. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00245.

REPRO-2026-00245 Command Injection Jul 6, 2026 CVE entry .txt
Severity
HIGH
CVSS
8.8
Confidence
HIGH
Reproduced in
50m 51s
Tool calls
313
Spend
$7.51
01 · Overview

What Is CVE-2026-34594?

CVE-2026-34594 is a high-severity authenticated OS command injection (CWE-78) in Coolify's Destination Network Management feature, letting a user with destination-management permissions execute arbitrary commands as root on the Coolify-managed host. Pruva reproduced it (reproduction REPRO-2026-00245).

02 · Severity & CVSS

CVE-2026-34594 Severity & CVSS Score

CVE-2026-34594 is rated high severity, with a CVSS base score of 8.8 out of 10.

HIGH threat level
8.8 / 10 CVSS base

How to Reproduce CVE-2026-34594

$ pruva-verify REPRO-2026-00245
or curl -O https://www.pruva.dev/api/v1/reproductions/REPRO-2026-00245/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

Proof of Reproduction for CVE-2026-34594

Remote code execution — reproduced
  • reached the target end-to-end
  • full exploit chain demonstrated
  • on the real production code path
  • high confidence
  • the upstream fix blocks the same trigger
Trigger

Destination Network Management 'network' field = x;id > /tmp/coolify_net_pwned 2>&1 # (shell metacharacters ; > #)

Attack chain
  1. Authenticated POST /livewire/update driving destination.new.docker submit()
  2. StandaloneDocker::create(['network'=>...])
  3. StandaloneDocker::created boot event
  4. instant_remote_process(['docker network inspect <network> ...'],$server)
  5. SshMultiplexingHelper::generateSshCommand
  6. ssh root@server 'bash -se' << delim (unsanitized network executed by remote bash)
Runnable proof: reproduction_steps.sh
Captured evidence: vulnerable attempt 1fixed attempt 1vulnerable attempt 2fixed attempt 2
How the agent worked 749 events · 313 tool calls · 51 min
51 minDuration
313Tool calls
189Reasoning steps
749Events
3Dead-ends
Agent activity over 51 min
Support
21
Repro
449
Judge
19
Variant
256
0:0050:51

Root Cause and Exploit Chain for CVE-2026-34594

Versions: Coolify < 4.0.0-beta.471 (verified on the official

Coolify (self-hosted PaaS, Laravel/Livewire application) before 4.0.0-beta.471 contains an authenticated command-injection vulnerability in the Destination Network Management functionality. The network field of a Docker Destination (App\Livewire\Destination\New\Docker and App\Livewire\Destination\Show) was only validated as ['required','string'], so an authenticated user with destination-management permissions could submit a value containing shell metacharacters. That value is stored on the StandaloneDocker / SwarmDocker model and later interpolated unsanitized into shell commands that Coolify executes on the destination's server over SSH (instant_remote_process()SshMultiplexingHelper::generateSshCommand()ssh ... 'bash -se' << $delimiter). Because the network string becomes the body of a here-doc fed to bash -se on the remote host, an attacker-controlled network such as x;id > /tmp/pwned # results in arbitrary command execution as root on the Coolify-managed server at the moment the destination is created (the StandaloneDocker::created boot event) and again when it is deleted.

  • Package/component affected: coollabsio/coolify — Destination Network Management (app/Livewire/Destination/New/Docker.php, app/Livewire/Destination/Show.php, app/Models/StandaloneDocker.php, app/Models/SwarmDocker.php, and every shell consumer of ->destination->network: ApplicationDeploymentJob, DatabaseBackupJob, StartService, Init command, bootstrap/helpers/proxy.php).
  • Affected versions: Coolify < 4.0.0-beta.471 (verified on the official image ghcr.io/coollabsio/coolify:4.0.0-beta.470).
  • Risk level: High. Coolify executes SSH commands with the destination server's user (default root). The injected command runs with that privilege on the managed host, enabling full server compromise, access to the Docker socket, lateral movement, and exposure of all managed resources / secrets. Exploitation requires only an authenticated user who can create a destination (the StandaloneDockerPolicy::create check returns true for any authenticated user; createAnyResource likewise returns true).

Impact Parity

  • Disclosed/claimed maximum impact: Authenticated command execution ("arbitrary command execution on the Coolify host") via the Destination Network Management network field.
  • Reproduced impact from this run: Authenticated command execution as root on the destination server. The injected id command wrote uid=0(root) gid=0(root) groups=0(root) to a marker file on the managed server, proving arbitrary command execution with root privileges through the authenticated web request.
  • Parity: full — the claimed authenticated command injection was demonstrated end-to-end against the real product, and the fixed build rejects the same input with no execution.

Root Cause

The network attribute of a Docker Destination is attacker-controlled input that flows into privileged shell commands without validation or escaping.

Vulnerable code path (beta.470):

  1. app/Livewire/Destination/New/Docker.php declares the field with only #[Validate(['required','string'])] (no character whitelist), and submit() calls StandaloneDocker::create(['network' => $this->network, ...]).
  2. app/Models/StandaloneDocker.php boot() registers a static::created hook that runs:
    instant_remote_process([
        "docker network inspect $newStandaloneDocker->network >/dev/null 2>&1 || docker network create --driver overlay --attachable $newStandaloneDocker->network >/dev/null",
    ], $server, false);
    
    The network is interpolated directly into the command string.
  3. instant_remote_process() builds an SSH command via SshMultiplexingHelper::generateSshCommand(), which sends the command as the body of a here-doc to bash -se on the remote server:
    timeout <t> ssh ... 'root'@'<ip>' 'bash -se' << $delimiter
    <command containing the unsanitized network>
    $delimiter
    
    escapedUserAtHost() escapes user@ip, but the command body (the network) is never escaped, so shell metacharacters in network are interpreted by the remote bash. ; breaks out of the docker network inspect token, the attacker command runs, and # comments out the rest of the line. The same unsanitized interpolation exists in Destination/Show.php::delete() and across ApplicationDeploymentJob, DatabaseBackupJob, StartService, Init, and proxy.php.

Fix (PR #9228, released in 4.0.0-beta.471, commit 3d1b9f53a0aec74468be75675bcaaaed0fd41d46; release tag commit 914d7e0b50505bc1fd56c34974fca09ad354e92a):

  • Adds DOCKER_NETWORK_PATTERN = '/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/' in app/Support/ValidationPatterns.php and applies it as a regex validation rule on the network field in both Livewire components.
  • Adds a setNetworkAttribute() mutator on StandaloneDocker and SwarmDocker that throws InvalidArgumentException for names not matching the pattern.
  • Applies escapeshellarg() to every shell usage of the network field.

Reproduction Steps

  1. Reference: bundle/repro/reproduction_steps.sh (self-contained).
  2. What the script does:
    • Installs the docker compose v2 plugin if missing and pulls the official Coolify images (4.0.0-beta.470 vulnerable, 4.0.0-beta.471 fixed) plus postgres:15-alpine, redis:7-alpine, coolify-testing-host (an SSH-enabled target whose authorized_keys matches a hardcoded key) and coolify-realtime.
    • Brings up the real Coolify stack (Coolify Laravel app + Postgres + Redis + Soketi + the SSH target) on a private Docker network, with IS_WINDOWS_DOCKER_DESKTOP=true so the seeded localhost server targets coolify-testing-host.
    • Bootstraps an authenticated root user, the testing-host SSH private key, and a server pointing at coolify-testing-host (root, port 22).
    • From the coolify-testing-host container, runs an authenticated Python client against the live Coolify web app (http://coolify:8080): logs in via Laravel Fortify, loads /server/{uuid}/destinations, extracts the destination.new.docker Livewire snapshot, and POSTs /livewire/update setting network = "x;id > /tmp/coolify_net_pwned 2>&1 #" and calling submit().
    • Repeats for the fixed image as a negative control.
  3. Expected evidence:
    • Vulnerable build: the StandaloneDocker::created event runs the SSH command with the injected network; /tmp/coolify_net_pwned* on the SSH target contains uid=0(root) gid=0(root) groups=0(root), and the Livewire response redirects to the newly created destination.
    • Fixed build: the request is rejected with The network field format is invalid. (regex validation), no destination is created, and no marker file appears.

Evidence

  • bundle/logs/reproduction_steps.log — full orchestrated run log.
  • bundle/logs/stack_vulnerable.log, bundle/logs/setup_vulnerable.log — vulnerable stack bring-up and bootstrap.
  • bundle/logs/vulnerable_attempt_1.log, bundle/logs/vulnerable_attempt_2.log — exploit output for the vulnerable build (Livewire redirect to /destination/<uuid> → destination created).
  • bundle/logs/vulnerable_marker_content.txt — captured marker content (uid=0(root) gid=0(root) groups=0(root)).
  • bundle/logs/stack_fixed.log, bundle/logs/setup_fixed.log — fixed stack.
  • bundle/logs/fixed_attempt_1.log, bundle/logs/fixed_attempt_2.log — exploit output for the fixed build (VALIDATION_BLOCKED + The network field format is invalid., no redirect, no marker).
  • bundle/repro/runtime_manifest.json — runtime evidence manifest (entrypoint_kind=api_remote, service_started=true, healthcheck_passed=true, target_path_reached=true).

Key reproduced excerpts (from the interactive verification run):

  • Vulnerable: effects redirect=http://coolify:8080/destination/o1jvtyfefdzb8nxnyqv0lkd2; standalone_dockers row with network = x;id > /tmp/coolify_net_pwned 2>&1 # on server_id=1; marker /tmp/coolify_net_pwned = uid=0(root) gid=0(root) groups=0(root).
  • Fixed: effects redirect=None, response snippet The network field format is invalid.; no standalone_dockers row with the malicious network; marker file absent.

Environment: official Coolify Docker images on the shared Docker daemon; the authenticated HTTP client runs in the coolify-testing-host container (reaches coolify:8080 over the coolifynet-repro bridge); command execution is performed by Coolify over SSH (bash -se here-doc) from the coolify container to coolify-testing-host as root.

Recommendations / Next Steps

  • Upgrade to Coolify >= 4.0.0-beta.471 (PR #9228). The fix combines input validation (regex whitelist matching Docker network naming rules), a model mutator that rejects invalid names, and escapeshellarg() on every shell usage of the network field.
  • Defense-in-depth: audit every instant_remote_process() / remote_process() call site for user-controlled interpolation; prefer escapeshellarg() / escapeshellcmd() and validated whitelists for any field that becomes part of an SSH/Docker command string. Consider a shared helper that forbids raw string interpolation of model attributes into command strings.
  • Restrict destination-management permissions; do not expose the Coolify admin interface publicly.

Additional Notes

  • Idempotency: the script tears the stack down (docker compose down -v + hard cleanup of the fixed container/volume/network names) before each build, and setup.php is idempotent (locates the root user by email, fixes the password hash, ensures a single coolify-testing-host server). Two attempts are run per build with distinct marker paths (hence distinct network strings) to avoid the (server_id, network) unique constraint.
  • The Docker daemon in this environment is on a separate host from the script execution sandbox, so published host ports are not reachable from the sandbox; the authenticated client therefore runs inside the coolify-testing-host container and reaches Coolify over the private Docker network (http://coolify:8080). This is a genuine authenticated HTTP request to the running Coolify service; the command execution crosses a real SSH boundary from Coolify to the managed server.
  • No sanitizers (ASAN/UBSAN/etc.) are used; this is a real product-mode runtime proof. The negative control (fixed image) demonstrates the patch closes the injection without relying on sanitizer output.

CVE-2026-34594 Reproduction Transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.

Full session Replay every step — scrub the timeline or play it back.

Event 1/40
0:000:39
0:00
session startedaccounts/fireworks/routers/glm-5p2-fast · CVE-2026-34594 · REPRO-20
0:01
0:03
web search
0:05
web search
0:07
0:08
web search
0:09
web search
0:11
0:12
0:15
0:17
web search
0:18
web search
0:29
0:29
extract_facts
no facts extracted
0:30
0:30
0:30
supportrepro
0:31
0:31
0:31
0:32
0:32
0:32
0:35
0:35
0:36
0:36
0:39
08 · How to Fix

How to Fix CVE-2026-34594

Coming soon

Step-by-step mitigation and hardening guidance for CVE-2026-34594 — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: CVE-2026-34594

When does the CVE-2026-34594 command injection trigger?

It triggers at the moment the destination is created, via the StandaloneDocker::created boot event, and again when the destination is deleted, since every shell consumer of ->destination->network (ApplicationDeploymentJob, DatabaseBackupJob, StartService, the Init command, and proxy helpers) re-interpolates the unsanitized value.

Does exploiting CVE-2026-34594 require authentication?

Yes. It requires an authenticated Coolify user who already has destination-management permissions; it is not an unauthenticated remote code execution.

How severe is CVE-2026-34594?

It is rated high severity: an already-authorized but lower-trust user can escalate to root command execution on any server Coolify manages as a destination.

How can I reproduce CVE-2026-34594?

Download the verified script from this page and run it in an isolated environment against a Coolify instance before 4.0.0-beta.471. Create a Docker Destination whose network field contains shell metacharacters (e.g. x;id > /tmp/pwned #), and confirm the injected command executes as root on the destination server when the destination is created.
11 · References

References for CVE-2026-34594

Authoritative sources for CVE-2026-34594 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.