CVE-2026-72864 Overview
Dokploy is a free, self-hostable Platform as a Service (PaaS). CVE-2026-72864 is a missing authorization flaw [CWE-862] in the /docker-container-terminal WebSocket handler defined in apps/dokploy/server/wss/docker-container-terminal.ts. Prior to version 0.29.13, the handler authenticates callers with validateRequest but does not authorize the attacker-controlled containerId against the caller's role, organization, or service access. The handler passes the identifier directly to docker exec, letting any authenticated organization member obtain a root shell in arbitrary containers on the host. The issue is fixed in Dokploy 0.29.13.
Critical Impact
Any authenticated Dokploy member can spawn a root shell in any container managed by the instance, breaking multi-tenant isolation and enabling full compromise of hosted workloads.
Affected Products
- Dokploy self-hosted PaaS versions prior to 0.29.13
- apps/dokploy/server/wss/docker-container-terminal.ts WebSocket handler
- Related handlers docker-container-logs.ts and container stats endpoints sharing the same authorization gap
Discovery Timeline
- 2026-08-10 - CVE-2026-72864 published to NVD
- 2026-08-11 - Last updated in NVD database
Technical Details for CVE-2026-72864
Vulnerability Analysis
Dokploy exposes a WebSocket route at /docker-container-terminal that opens an interactive shell inside a Docker container. The server-side handler calls validateRequest to confirm the WebSocket originates from an authenticated session, then reads containerId from the client message and invokes docker exec against that identifier. Authentication was treated as sufficient, so no check verified whether the caller's role, organization, or service scope entitled them to attach to the requested container.
Because docker exec runs as the Docker daemon user, the attacker receives a root shell inside the target container. On a shared self-hosted Dokploy instance, a low-privileged tenant member can read secrets, modify files, and pivot into other tenants' workloads. The same authorization gap affects container logs and stats WebSocket endpoints, exposing runtime telemetry and log data across organization boundaries.
Root Cause
The root cause is missing authorization [CWE-862] between the WebSocket authentication layer and the Docker execution layer. The handler trusted the client-supplied containerId without consulting the permission service or verifying that the container belongs to a service the caller can access. There was no check that the calling member had the docker permission or, for remote servers, that the target server ID was accessible to the caller.
Attack Vector
An authenticated member of any organization on the Dokploy instance connects to the terminal WebSocket and supplies a containerId observed or guessed from another tenant. The handler proxies the connection to docker exec, delivering a root shell. Because Dokploy manages containers across organizations on the same host, cross-tenant container access is reachable over the network with only low-privileged credentials.
// Patch: apps/dokploy/server/wss/authorize.ts
// Source: https://github.com/Dokploy/dokploy/commit/68f5afae42fca353dcb3d3bc6219ffe9e168cb91
+import { getAccessibleServerIds } from "@dokploy/server";
+import {
+ findMemberByUserId,
+ hasPermission,
+} from "@dokploy/server/services/permission";
+
+type WssUser = { id: string } | null | undefined;
+type WssSession = { activeOrganizationId?: string | null } | null | undefined;
+
+const buildCtx = (user: { id: string }, activeOrganizationId: string) => ({
+ user: { id: user.id },
+ session: { activeOrganizationId },
+});
+
+// Authorizes docker/container operations opened over a WebSocket (container
+// terminal, container logs, container stats). Requires the docker permission
+// (owner/admin, or a member explicitly granted canAccessToDocker) and, for a
+// remote server, that the server is accessible to the caller. Previously these
+// handlers only checked session + organization, so any member could reach a
+// root shell / logs of any container.
+export const canAccessDockerOverWss = async (
+ user: WssUser,
+ session: WssSession,
+ serverId?: string | null,
+): Promise<boolean> => {
+ if (!user || !session?.activeOrganizationId) return false;
+
+ const ctx = buildCtx(user, session.activeOrganizationId);
+ if (!(await hasPermission(ctx, { docker: ["read"] }))) return false;
The companion patch wires the new authorization helper into the log handler and the terminal handler.
// Patch: apps/dokploy/server/wss/docker-container-logs.ts
// Source: https://github.com/Dokploy/dokploy/commit/68f5afae42fca353dcb3d3bc6219ffe9e168cb91
import { spawn } from "node-pty";
import { Client } from "ssh2";
import { WebSocketServer } from "ws";
+import { canAccessDockerOverWss } from "./authorize";
import {
getShell,
isValidContainerId,
Detection Methods for CVE-2026-72864
Indicators of Compromise
- Unexpected WebSocket upgrade requests to /docker-container-terminal, /docker-container-logs, or container stats endpoints from low-privileged user sessions.
- docker exec invocations spawning interactive shells (/bin/sh, /bin/bash) with parent process node from the Dokploy server.
- Container terminal sessions targeting containerId values that do not belong to the authenticated user's organization or service ownership.
Detection Strategies
- Parse Dokploy application logs for terminal WebSocket sessions and correlate the caller's organization with the resolved container's owning service.
- Alert on docker exec -it processes launched outside of expected administrative windows or by non-admin user IDs.
- Compare pre- and post-upgrade audit trails for the Dokploy web tier to spot sessions that opened container shells without corresponding permission checks in the log stream.
Monitoring Recommendations
- Enable verbose audit logging on the Docker daemon (--log-level=info or higher) and forward events to a centralized log platform.
- Track file modifications inside containers via runtime tooling to catch post-exploitation activity following unauthorized shell access.
- Monitor authentication events for accounts that generate an unusually high number of container terminal or log sessions.
How to Mitigate CVE-2026-72864
Immediate Actions Required
- Upgrade all Dokploy instances to version 0.29.13 or later, which introduces canAccessDockerOverWss and enforces the docker permission on terminal, logs, and stats WebSockets.
- Rotate secrets, API tokens, and credentials stored in containers that were reachable during the exposure window, since a root shell could have exfiltrated them.
- Audit organization member lists and remove accounts that should not retain access to the shared instance.
Patch Information
The fix is delivered in Dokploy 0.29.13. See the GitHub Release v0.29.13, the GitHub Security Advisory GHSA-899j-cjwp-v4gw, and the remediation commit. The commit adds an authorize.ts helper that validates the session, checks the docker: ["read"] permission via hasPermission, and confirms server accessibility with getAccessibleServerIds before allowing the WebSocket to proceed.
Workarounds
- Restrict Dokploy organization membership to trusted administrators until the patch is deployed, since any member can reach the vulnerable endpoint.
- Place the Dokploy web tier behind a reverse proxy that blocks WebSocket upgrades to /docker-container-terminal, /docker-container-logs, and container stats routes for non-admin users.
- Segment self-hosted Dokploy deployments so that untrusted tenants do not share a Docker host with sensitive workloads.
# Upgrade Dokploy to the patched release
docker pull dokploy/dokploy:0.29.13
docker service update --image dokploy/dokploy:0.29.13 dokploy
# Temporary NGINX block for the vulnerable WebSocket route
location ~ ^/docker-container-(terminal|logs)$ {
return 403;
}
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

