Flyto2 Core: Multiple HTTP-family modules fetch client-controlled URLs without the SSRF guard their siblings apply (SSRF to internal/metadata)
Summary
Numerous HTTP-emitting modules (core.api.http_get, core.api.http_post, graphql.query/graphql.mutation, monitor.http_check, communication.slack_send, notification.{discord,slack,teams}.send_message, ai.vision_analyze [anthropic path], verify.visual_diff, browser.proxy_rotate, and the agent/llm inline base_url branch) perform outbound requests to a fully client-controlled URL without calling the project's own SSRF guard (validate_url_with_env_config) that their sibling modules apply. An authenticated workflow-author can point the URL at the cloud metadata IP (169.254.169.254), a loopback/RFC1918 host, or any internal host and read the response, yielding cloud-metadata credential theft and internal service read/write.
Root Cause
The SSRF guard is per-module (there is NO global egress interception). Each module must call validate_url_with_env_config before issuing a request. The listed modules never call it — they only carry an ssrf_protected metadata tag string which enforces nothing. Exemplar: src/core/modules/third_party/developer/http/requests.py — grepping for validate_url|ssrf|is_private in requests.py returns 0 guard calls; session.get(url) fires at :85 (HTTPGetModule) and session.post at :188 (HTTPPostModule). SECURITY.md incorrectly lists api.http_get as SSRF-protected.
Impact
Readable SSRF: full {status_code, headers, body} returned to the caller (requests.py:96-108). Enables theft of cloud IAM credentials from the metadata endpoint and read/write access to internal-only APIs. Scope Changed (S:C) — the request crosses into cloud-metadata / internal-network authority the workflow layer does not otherwise have.
Proof of Concept
Verified live this session: core.api.http_get with url pointed at a loopback internal server returned the internal body INTERNAL-SECRET-IAM-CREDENTIALS, while the guarded sibling http.get returned NETWORK_ERROR: Hostname blocked: 127.0.0.1 on the same input — proving the branch-asymmetry is real (not a port artifact).
POST /mcp {"method":"tools/call","params":{"name":"execute_module",
"arguments":{"module_id":"core.api.http_get",
"params":{"url":"http://<cloud-metadata-ip>/latest/meta-data/iam/security-credentials/"}}}}
Attack Chain
- Entry: authenticated MCP client →
POST /mcpexecute_modulecore.api.http_get, url set to the cloud metadata endpoint. Guard:require_auth(mcp.py:71). Bypass proof: passes with a valid workflow-author bearer token (PR:L). - Check: capability denylist /
enforce_module_policy(base.py:240). Bypass proof:core.api.*not in_DEFAULT_DENYLIST(module_policy.py:45-67) →is_allowed=True(runtime-registration verified:core.api.http_get -> HTTPGetModule). - Check: SSRF validation. Bypass proof:
requests.pyhas ZEROvalidate_url/ssrf calls — only thessrf_protectedtag string at :23/:116.session.get(url)fires at :85. - Sink: aiohttp GET/POST to the cloud metadata IP.
- Impact: full response body returned → IAM credential theft, internal read/write.
Bypass Evidence
Grepping validate_url|ssrf|is_private in requests.py → 0 guard calls (2 hits are both the inert tag string). Live PoC returned internal body directly; guarded sibling blocked the same input. Direct IP works — no IPv6 transition trick needed (AC:L), unlike the seed CVE-2026-55787.
Affected Versions
<= 2.26.6 — code present on latest release tag v2.26.6 (requests.py:19,112).
Suggested Fix
Call validate_url_with_env_config(url) in each listed module before issuing the outbound request, matching the guarded siblings (e.g. ai.model:157, http.get). Best: route all outbound HTTP through a single guarded client wrapper so new modules inherit the guard.
Credit
Vulnerability discovered by zx (Jace).
Affected software
Click a technology to see all vulnerabilities affecting it.
| Platform | Package | Vulnerable versions | Fixed in |
|---|---|---|---|
| Python (PyPI) | flyto-core | < 2.26.7 | 2.26.7 |
References
- https://github.com/flytohub/flyto-core/security/advisories/GHSA-pgwh-4jj4-qm8v
- https://nvd.nist.gov/vuln/detail/CVE-2026-67428
- https://github.com/flytohub/flyto-core/commit/0a0a528520ec18f5a21f1ddf858a71cc1edfb6e9
- https://github.com/flytohub/flyto-core
- https://github.com/flytohub/flyto-core/releases/tag/v2.26.7
- https://pypi.org/project/flyto-core
- https://github.com/advisories/GHSA-pgwh-4jj4-qm8v
- CVSS vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N- Weakness (CWE)
CWE-918- Platform
- Python (PyPI)
- Package
flyto-core- Disclosed
- 30.07.2026
- Updated
- 11.10.2026 14:19
Sources and licenses
OSV / GitHub Advisory Database - PYSEC-2026-3572 - PyPA Advisory Database; CC BY 4.0
OSV / GitHub Advisory Database - GHSA-pgwh-4jj4-qm8v - CC BY 4.0
Vulnerability history: flyto-core
All published vulnerabilities of this package (Python (PyPI)), newest first. Shows whether this is a one-off slip or a package that needs watching.
- Total entries
- 8
- First → latest
- 07.2026 07.2026
- Without a fix
- 0
- Exploited in attacks
- 0
Severity breakdown
- Critical 2
- High 6
Disclosures per year
- 2026: 8
-
Flyto2 Core: Multiple HTTP-family modules fetch client-controlled URLs without the SSRF guard their siblings apply (SSRF to internal/metadata) this entry
Know which vulnerabilities affect your application
With the DockRay integration and software inventory enabled, DockRay checks reported component versions against known vulnerabilities and notifies you about confirmed matches. Coverage depends on the supported technology and available advisory data.