CVE-2026-67428: Flyto2 Core: Multiple HTTP-family modules fetch client-controlled URLs without the SSRF guard their siblings apply (SSRF to internal/metadata)
Many HTTP-making modules in flyto-core, including core.api.http_get and http_post, fetch a caller-supplied URL without calling the project's SSRF guard. An authenticated workflow author, or an agent acting for one, can reach the cloud metadata endpoint or internal hosts and read the response. Versions up to 2.26.6 are affected. Fixed in 2.26.7.
Published Jul 30, 2026 · Analysis Oct 25, 2026
What an attacker can do
flyto-core's SSRF guard, validate_url_with_env_config, is per-module. There is no global egress filter. The affected modules never call it and only carry an ssrf_protected tag string that enforces nothing. In developer/http/requests.py, session.get(url) runs at line 85 and session.post at line 188 with no check. SECURITY.md wrongly lists api.http_get as protected.
The affected set: core.api.http_get and http_post, graphql.query and mutation, monitor.http_check, communication.slack_send, the Discord, Slack and Teams notification modules, ai.vision_analyze on its Anthropic path, verify.visual_diff, browser.proxy_rotate, and the inline base_url branch of agent and llm.
The response (status code, headers, body) comes back to the caller. In the reporter's test, core.api.http_get returned an internal body from a loopback server while the guarded sibling http.get answered Hostname blocked: 127.0.0.1. A direct IP works, so no bypass trick is needed. The attacker needs a valid workflow-author token on POST /mcp execute_module, or a prompt-injected agent. They can steal cloud IAM credentials from 169.254.169.254 and read or write internal services.
Who is affected
flyto-core 2.26.6 and earlier (pip package flyto-core). The vulnerable code was confirmed on the v2.26.6 release tag. The core.api.* modules were not on the default module denylist, so they were callable out of the box.
pip show flyto-coreflyto-core
- Ecosystem
- PyPI
- Affected
- <= 2.26.6
- Fixed in
- 2.26.7
- Check
pip show flyto-core
How to fix it
Upgrade to flyto-core 2.26.7:
pip install --upgrade flyto-core==2.26.7The fix commit adds an enforce_outbound_url() helper and calls it before outbound requests in the listed modules, including requests.py, vision_analyze, proxy_rotate, slack_send, the graphql modules, monitor.http_check and verify.visual_diff. Most raise an error wrapping SSRFError. http_check and visual_diff return error_code SSRF_BLOCKED instead.
The same commit also adds redirect revalidation for http.get, http.request and http.batch, capped at 5 hops, and requires a shared key on the verification /run endpoint. Those are covered by separate advisories. Block metadata-endpoint access from the host as defense in depth.
How to tell if you were hit
Review MCP and API logs for execute_module calls to core.api.http_get, http_post, graphql, monitor.http_check or notification modules whose url points at 169.254.169.254, loopback, RFC1918 ranges or internal hostnames. On the network side, look for requests from the flyto-core host to the metadata service. If one occurred, treat the instance role credentials as exposed and rotate them. After the upgrade, SSRF_BLOCKED results or SSRFError exceptions mark blocked attempts. Beam records agent MCP tool calls, so such execute_module arguments can be reviewed.
Original advisory
From the GitHub Advisory Database (CC BY 4.0).
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).
Credited to manus-use.
Questions
- Why did http.get block the request but core.api.http_get did not?
http.get calls the SSRF guard before sending. core.api.http_get never did; it carried only a metadata tag. The reporter's test showed the same loopback input blocked by one and served by the other.
- Does the attacker need an account?
The advisory scores low privileges: a valid workflow-author bearer token on POST /mcp. A prompt-injected agent that holds such access can do the same.
- Which version fixes CVE-2026-67428?
flyto-core 2.26.7. Versions up to 2.26.6 are affected.
References
How this page is made: the data panel comes from the GitHub Advisory Database, CISA’s KEV catalog, the NVD and FIRST EPSS, and updates twice a day. The analysis is written by an AI model from the sources listed above and checked by automated rules before it is published. Check versions against the vendor's advisory before you act. Methodology
More Other MCP servers and tools vulnerabilities
All Other MCP servers and tools entriesCVE-2026-77361
obsidian-tc : Symlink read-ACL scope bypass via lexical path checks
medium4.7Oct 23, 2026CVE-2026-114126
Storybook dev server vulnerable to code injection from the local network
high8.7Oct 22, 2026CVE-2026-113731
djust: Arbitrary absolute-path file read in the find_handlers_for_template MCP tool
low3.3Oct 21, 2026CVE-2026-114125
Storybook: Missing origin validation in Storybook preview allows code injection from malicious websites
critical9.4Oct 21, 2026CVE-2026-111770
MCP TypeScript server SDK: Shared transport or server instances delivered one HTTP client's messages to another
high7.7Oct 20, 2026GHSA-953h-535j-jg2v
agent-router: MCP session resume does not verify the embedded anti-hijacking subject; default Helm seed makes session IDs forgeable
medium6.8Oct 19, 2026
