{"id":"CVE-2026-67428","aliases":["EUVD-2026-50472","GHSA-pgwh-4jj4-qm8v","PYSEC-2026-3572"],"status":"published","title":"Flyto2 Core: Multiple HTTP-family modules fetch client-controlled URLs without the SSRF guard their siblings apply (SSRF to internal/metadata)","description":"Flyto2 Core is an execution kernel for automation and AI-agent workflows. Prior to 2.26.7, HTTP-emitting modules including src/core/modules/third_party/developer/http/requests.py, core.api.http_get, core.api.http_post, graphql.query, graphql.mutation, monitor.http_check, communication.slack_send, notification.discord.send_message, notification.slack.send_message, notification.teams.send_message, ai.vision_analyze, verify.visual_diff, browser.proxy_rotate, and the agent and llm inline base_url branch fetch caller-controlled URLs without validate_url_with_env_config, allowing SSRF to internal or metadata endpoints. This issue is fixed in version 2.26.7.","severity":{"version":"3.1","score":8.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-09","score":0.00409,"percentile":0.35466,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-918"],"published":"2026-07-29T18:48:42Z","modified":"2026-10-28T02:30:58Z","fixes":[{"ecosystem":"PyPI","package":"flyto-core","fixed_in":["2.26.7"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"PyPI","package":"flyto-core","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"2.26.6"},{"fixed":"2.26.7"}]}]},{"source":"osv","ecosystem":"PyPI","package":"flyto-core","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.26.7"}]}],"versions":["1.0.0","1.0.1","1.0.2","1.0.3","1.0.4","1.0.5","1.0.6","1.0.7","1.0.8","1.0.9","1.1.0","1.1.1","1.11.0","1.12.0","1.13.0","1.14.0","1.14.1","1.14.2","1.15.0","1.16.0","1.16.1","1.16.10","1.16.2","1.16.3","1.16.4","1.16.5","1.16.6","1.16.7","1.16.8","1.16.9","1.2.0","1.3.0","1.4.0","1.5.0","1.5.1","1.5.2","1.5.4","1.6.0","1.6.1","1.6.2","1.6.3","1.6.4","1.6.5","1.7.0","1.7.1","1.7.2","1.7.3","1.7.4","1.7.5","1.7.6","1.7.7","1.7.8","1.7.9","1.8.0","1.8.1","1.8.10","1.8.11","1.8.12","1.8.13","1.8.14","1.8.15","1.8.16","1.8.17","1.8.2","1.8.3","1.8.4","1.8.5","1.8.6","1.8.7","1.8.8","1.8.9","1.9.0","2.0.0","2.0.1","2.0.2","2.0.3","2.0.4","2.0.5","2.1.0","2.1.1","2.1.2","2.1.3","2.1.4","2.10.0","2.11.0","2.12.0","2.12.1","2.12.13","2.12.15","2.12.16","2.12.17","2.12.18","2.12.19","2.12.2","2.12.20","2.12.21","2.12.22","2.12.23","2.12.24","2.12.25","2.12.26","2.12.27","2.12.28","2.12.3","2.12.4","2.12.5","2.12.6","2.13.0","2.13.1","2.13.2","2.13.3","2.13.4","2.14.0","2.15.0","2.15.1","2.15.2","2.15.3","2.16.1","2.16.3","2.16.4","2.17.0","2.17.1","2.17.2","2.17.3","2.17.4","2.17.5","2.17.6","2.17.7","2.17.8","2.18.0","2.18.1","2.18.10","2.18.11","2.18.2","2.18.3","2.18.4","2.18.5","2.18.6","2.18.8","2.18.9","2.19.0","2.2.0","2.2.1","2.2.2","2.20.0","2.20.1","2.20.2","2.20.3","2.20.4","2.23.0","2.23.1","2.23.2","2.23.3","2.24.0","2.24.1","2.24.2","2.24.3","2.24.4","2.25.0","2.25.1","2.25.10","2.25.11","2.25.12","2.25.13","2.25.14","2.25.15","2.25.16","2.25.17","2.25.18","2.25.19","2.25.2","2.25.20","2.25.21","2.25.22","2.25.23","2.25.24","2.25.25","2.25.26","2.25.27","2.25.3","2.25.4","2.25.5","2.25.6","2.25.7","2.25.8","2.25.9","2.26.0","2.26.1","2.26.2","2.26.3","2.26.4","2.26.5","2.3.0","2.3.1","2.4.0","2.4.1","2.4.2","2.4.3","2.4.4","2.4.5","2.4.6","2.4.7","2.5.0","2.5.1","2.5.2","2.6.0","2.6.1","2.7.0","2.7.1","2.7.2","2.7.3","2.7.4","2.7.5","2.7.6","2.8.0","2.9.0"]},{"source":"osv","ecosystem":"PyPI","package":"flyto-core","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.26.7"}]}],"versions":["1.0.0","1.0.1","1.0.2","1.0.3","1.0.4","1.0.5","1.0.6","1.0.7","1.0.8","1.0.9","1.1.0","1.1.1","1.11.0","1.12.0","1.13.0","1.14.0","1.14.1","1.14.2","1.15.0","1.16.0","1.16.1","1.16.10","1.16.2","1.16.3","1.16.4","1.16.5","1.16.6","1.16.7","1.16.8","1.16.9","1.2.0","1.3.0","1.4.0","1.5.0","1.5.1","1.5.2","1.5.4","1.6.0","1.6.1","1.6.2","1.6.3","1.6.4","1.6.5","1.7.0","1.7.1","1.7.2","1.7.3","1.7.4","1.7.5","1.7.6","1.7.7","1.7.8","1.7.9","1.8.0","1.8.1","1.8.10","1.8.11","1.8.12","1.8.13","1.8.14","1.8.15","1.8.16","1.8.17","1.8.2","1.8.3","1.8.4","1.8.5","1.8.6","1.8.7","1.8.8","1.8.9","1.9.0","2.0.0","2.0.1","2.0.2","2.0.3","2.0.4","2.0.5","2.1.0","2.1.1","2.1.2","2.1.3","2.1.4","2.10.0","2.11.0","2.12.0","2.12.1","2.12.13","2.12.15","2.12.16","2.12.17","2.12.18","2.12.19","2.12.2","2.12.20","2.12.21","2.12.22","2.12.23","2.12.24","2.12.25","2.12.26","2.12.27","2.12.28","2.12.3","2.12.4","2.12.5","2.12.6","2.13.0","2.13.1","2.13.2","2.13.3","2.13.4","2.14.0","2.15.0","2.15.1","2.15.2","2.15.3","2.16.1","2.16.3","2.16.4","2.17.0","2.17.1","2.17.2","2.17.3","2.17.4","2.17.5","2.17.6","2.17.7","2.17.8","2.18.0","2.18.1","2.18.10","2.18.11","2.18.2","2.18.3","2.18.4","2.18.5","2.18.6","2.18.8","2.18.9","2.19.0","2.2.0","2.2.1","2.2.2","2.20.0","2.20.1","2.20.2","2.20.3","2.20.4","2.23.0","2.23.1","2.23.2","2.23.3","2.24.0","2.24.1","2.24.2","2.24.3","2.24.4","2.25.0","2.25.1","2.25.10","2.25.11","2.25.12","2.25.13","2.25.14","2.25.15","2.25.16","2.25.17","2.25.18","2.25.19","2.25.2","2.25.20","2.25.21","2.25.22","2.25.23","2.25.24","2.25.25","2.25.26","2.25.27","2.25.3","2.25.4","2.25.5","2.25.6","2.25.7","2.25.8","2.25.9","2.26.0","2.26.1","2.26.2","2.26.3","2.26.4","2.26.5","2.3.0","2.3.1","2.4.0","2.4.1","2.4.2","2.4.3","2.4.4","2.4.5","2.4.6","2.4.7","2.5.0","2.5.1","2.5.2","2.6.0","2.6.1","2.7.0","2.7.1","2.7.2","2.7.3","2.7.4","2.7.5","2.7.6","2.8.0","2.9.0"]}],"products":[{"vendor":"flytohub","product":"flyto-core"}],"references":[{"url":"https://github.com/flytohub/flyto-core/security/advisories/GHSA-pgwh-4jj4-qm8v","tags":["x_refsource_CONFIRM","exploit","advisory","web"]},{"url":"https://github.com/flytohub/flyto-core/commit/0a0a528520ec18f5a21f1ddf858a71cc1edfb6e9","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/flytohub/flyto-core/releases/tag/v2.26.7","tags":["x_refsource_MISC","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-67428","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-pgwh-4jj4-qm8v","tags":["advisory"]},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/67xxx/CVE-2026-67428.json","tags":["advisory"]},{"url":"https://github.com/flytohub/flyto-core","tags":["package"]},{"url":"https://pypi.org/project/flyto-core","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-67428","title":"Flyto2 Core: Multiple HTTP-family modules fetch client-controlled URLs without the SSRF guard their siblings apply (SSRF to internal/metadata)","description":"Flyto2 Core is an execution kernel for automation and AI-agent workflows. Prior to 2.26.7, HTTP-emitting modules including src/core/modules/third_party/developer/http/requests.py, core.api.http_get, core.api.http_post, graphql.query, graphql.mutation, monitor.http_check, communication.slack_send, notification.discord.send_message, notification.slack.send_message, notification.teams.send_message, ai.vision_analyze, verify.visual_diff, browser.proxy_rotate, and the agent and llm inline base_url branch fetch caller-controlled URLs without validate_url_with_env_config, allowing SSRF to internal or metadata endpoints. This issue is fixed in version 2.26.7.","status":"published","published":"2026-07-29T18:48:42.087Z","modified":"2026-07-30T14:33:40.622Z","cvss":[{"version":"3.1","score":8.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N","level":"high","assessor":"cna"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T14:20:06.562031Z"}],"euvd":[{"id":"EUVD-2026-50472","description":"Flyto2 Core is an execution kernel for automation and AI-agent workflows. Prior to 2.26.7, HTTP-emitting modules including src/core/modules/third_party/developer/http/requests.py, core.api.http_get, core.api.http_post, graphql.query, graphql.mutation, monitor.http_check, communication.slack_send, notification.discord.send_message, notification.slack.send_message, notification.teams.send_message, ai.vision_analyze, verify.visual_diff, browser.proxy_rotate, and the agent and llm inline base_url branch fetch caller-controlled URLs without validate_url_with_env_config, allowing SSRF to internal or metadata endpoints. This issue is fixed in version 2.26.7.","status":"published","published":"2026-07-29T18:48:42Z","modified":"2026-07-30T14:33:40Z","cvss":[{"version":"3.1","score":8.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N","level":"high"}],"updated_at":"2026-11-02T18:02:28.93005Z"}],"ghsa":[{"id":"GHSA-pgwh-4jj4-qm8v","title":"Flyto2 Core: Multiple HTTP-family modules fetch client-controlled URLs without the SSRF guard their siblings apply (SSRF to internal/metadata)","description":"## Summary\nNumerous 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.\n\n## Root Cause\nThe 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.\n\n## Impact\nReadable 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.\n\n## Proof of Concept\nVerified 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).\n```\nPOST /mcp {\"method\":\"tools/call\",\"params\":{\"name\":\"execute_module\",\n  \"arguments\":{\"module_id\":\"core.api.http_get\",\n  \"params\":{\"url\":\"http://\u003ccloud-metadata-ip\u003e/latest/meta-data/iam/security-credentials/\"}}}}\n```\n\n## Attack Chain\n1. Entry: authenticated MCP client → `POST /mcp` execute_module `core.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).\n2. 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 -\u003e HTTPGetModule`).\n3. Check: SSRF validation. Bypass proof: `requests.py` has ZERO `validate_url`/ssrf calls — only the `ssrf_protected` tag string at :23/:116. `session.get(url)` fires at :85.\n4. Sink: aiohttp GET/POST to the cloud metadata IP.\n5. Impact: full response body returned → IAM credential theft, internal read/write.\n\n## Bypass Evidence\nGrepping `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.\n\n## Affected Versions\n`\u003c= 2.26.6` — code present on latest release tag v2.26.6 (`requests.py:19,112`).\n\n## Suggested Fix\nCall `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.\n\n## Credit\n\nVulnerability discovered by zx (Jace).","status":"published","published":"2026-07-30T14:48:05Z","modified":"2026-07-30T14:48:09Z","cvss":[{"version":"3.1","score":8.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N","level":"high"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T14:40:54.767849Z"}],"nvd":[{"id":"CVE-2026-67428","description":"Flyto2 Core is an execution kernel for automation and AI-agent workflows. Prior to 2.26.7, HTTP-emitting modules including src/core/modules/third_party/developer/http/requests.py, core.api.http_get, core.api.http_post, graphql.query, graphql.mutation, monitor.http_check, communication.slack_send, notification.discord.send_message, notification.slack.send_message, notification.teams.send_message, ai.vision_analyze, verify.visual_diff, browser.proxy_rotate, and the agent and llm inline base_url branch fetch caller-controlled URLs without validate_url_with_env_config, allowing SSRF to internal or metadata endpoints. This issue is fixed in version 2.26.7.","status":"published","published":"2026-07-29T19:16:52.087Z","modified":"2026-10-24T13:10:00.147Z","cvss":[{"version":"3.1","score":8.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N","level":"high","assessor":"secondary"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T14:12:33.629616Z"}],"osv":[{"id":"CVE-2026-67428","title":"Flyto2 Core: Multiple HTTP-family modules fetch client-controlled URLs without the SSRF guard their siblings apply (SSRF to internal/metadata)","description":"Flyto2 Core is an execution kernel for automation and AI-agent workflows. Prior to 2.26.7, HTTP-emitting modules including src/core/modules/third_party/developer/http/requests.py, core.api.http_get, core.api.http_post, graphql.query, graphql.mutation, monitor.http_check, communication.slack_send, notification.discord.send_message, notification.slack.send_message, notification.teams.send_message, ai.vision_analyze, verify.visual_diff, browser.proxy_rotate, and the agent and llm inline base_url branch fetch caller-controlled URLs without validate_url_with_env_config, allowing SSRF to internal or metadata endpoints. This issue is fixed in version 2.26.7.","status":"published","published":"2026-07-29T18:48:42.087Z","modified":"2026-10-28T02:30:58.978689146Z","cvss":[{"version":"3.1","score":8.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N","level":"high"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T15:45:14.46177Z"},{"id":"GHSA-pgwh-4jj4-qm8v","title":"Flyto2 Core: Multiple HTTP-family modules fetch client-controlled URLs without the SSRF guard their siblings apply (SSRF to internal/metadata)","description":"## Summary\nNumerous 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.\n\n## Root Cause\nThe 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.\n\n## Impact\nReadable 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.\n\n## Proof of Concept\nVerified 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).\n```\nPOST /mcp {\"method\":\"tools/call\",\"params\":{\"name\":\"execute_module\",\n  \"arguments\":{\"module_id\":\"core.api.http_get\",\n  \"params\":{\"url\":\"http://\u003ccloud-metadata-ip\u003e/latest/meta-data/iam/security-credentials/\"}}}}\n```\n\n## Attack Chain\n1. Entry: authenticated MCP client → `POST /mcp` execute_module `core.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).\n2. 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 -\u003e HTTPGetModule`).\n3. Check: SSRF validation. Bypass proof: `requests.py` has ZERO `validate_url`/ssrf calls — only the `ssrf_protected` tag string at :23/:116. `session.get(url)` fires at :85.\n4. Sink: aiohttp GET/POST to the cloud metadata IP.\n5. Impact: full response body returned → IAM credential theft, internal read/write.\n\n## Bypass Evidence\nGrepping `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.\n\n## Affected Versions\n`\u003c= 2.26.6` — code present on latest release tag v2.26.6 (`requests.py:19,112`).\n\n## Suggested Fix\nCall `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.\n\n## Credit\n\nVulnerability discovered by zx (Jace).","status":"published","published":"2026-07-30T14:48:05Z","modified":"2026-08-04T14:40:46.157327053Z","cvss":[{"version":"3.1","score":8.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N","level":"high"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T15:46:53.244788Z"},{"id":"PYSEC-2026-3572","title":"Flyto2 Core: Multiple HTTP-family modules fetch client-controlled URLs without the SSRF guard their siblings apply (SSRF to internal/metadata)","description":"## Summary\nNumerous 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.\n\n## Root Cause\nThe 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.\n\n## Impact\nReadable 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.\n\n## Proof of Concept\nVerified 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).\n```\nPOST /mcp {\"method\":\"tools/call\",\"params\":{\"name\":\"execute_module\",\n  \"arguments\":{\"module_id\":\"core.api.http_get\",\n  \"params\":{\"url\":\"http://\u003ccloud-metadata-ip\u003e/latest/meta-data/iam/security-credentials/\"}}}}\n```\n\n## Attack Chain\n1. Entry: authenticated MCP client → `POST /mcp` execute_module `core.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).\n2. 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 -\u003e HTTPGetModule`).\n3. Check: SSRF validation. Bypass proof: `requests.py` has ZERO `validate_url`/ssrf calls — only the `ssrf_protected` tag string at :23/:116. `session.get(url)` fires at :85.\n4. Sink: aiohttp GET/POST to the cloud metadata IP.\n5. Impact: full response body returned → IAM credential theft, internal read/write.\n\n## Bypass Evidence\nGrepping `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.\n\n## Affected Versions\n`\u003c= 2.26.6` — code present on latest release tag v2.26.6 (`requests.py:19,112`).\n\n## Suggested Fix\nCall `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.\n\n## Credit\n\nVulnerability discovered by zx (Jace).","status":"published","published":"2026-08-04T11:34:45.633302Z","modified":"2026-08-04T14:30:16.323180146Z","cvss":[{"version":"3.1","score":8.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N","level":"high"}],"updated_at":"2026-11-02T15:52:56.847083Z"}]}}
