# SSRF via redirects and scheme changes

URL validated once, then redirect or scheme switch reaches file, gopher, or internal hosts

_Area: Web infrastructure and server-side requests. Seen in 13 disclosed reports; 6 confirmed bounties, median $650, range $64-$22,300; latest 2024-01-31. Updated 2026-10-23._

## How it works
A server-side fetcher validates a URL, then hands it to a client that does more than the validator assumed. Two assumptions break: the URL checked is not the URL fetched (redirects change the destination after the check), and the scheme checked is not the scheme used (clients like git, curl, or Kernel.Open also honor file://, gopher://, or a downgraded http://). The guard sits at the wrong layer, so anything downstream that re-resolves, re-connects, or switches protocol bypasses it.

## Where it shows up
- URL validators called without an explicit scheme allowlist [E1](https://bugbountylibrary.com/r/h1%3A1685822.md)
- HTTP clients that follow redirects from user-supplied or whitelisted base URLs [E2](https://bugbountylibrary.com/r/blog%3Aassetnote-io-resources-research-turning-bad-ssrf-to-good-ssrf-websphere-portal-cve-2021-27748.md)[E5](https://bugbountylibrary.com/r/h1%3A508459.md)
- Anti-SSRF filters implemented as agent hooks (createConnection) [E4](https://bugbountylibrary.com/r/blog%3Ablog-doyensec-com-2023-03-16-ssrf-remediation-bypass-html.md)
- Fetchers using Kernel.Open or similar that resolve to loopback [E8](https://bugbountylibrary.com/r/h1%3A1092230.md)
- Image fetchers that honor non-HTTP schemes after a redirect [E6](https://bugbountylibrary.com/r/h1%3A811136.md)
- Route/controller params passed straight to a URL-fetching function [E7](https://bugbountylibrary.com/r/h1%3A895696.md)

## How to review
Trace the URL from input to the actual socket. The invariant: every hop, including each redirect target and each scheme, must be re-validated against the same allowlist before connection. Concretely: confirm the validator and fetcher agree on the scheme set; confirm redirects are disabled or re-checked per hop, in that order (re-check before connect, not after); confirm filters are not attached to swappable agents; confirm every 3xx status is handled, not just 301/302.

## Variants seen
- Scheme-less validation lets file:// reach git fetch [E1](https://bugbountylibrary.com/r/h1%3A1685822.md)
- Whitelisted host with an open redirect turns restricted SSRF into full-read [E2](https://bugbountylibrary.com/r/blog%3Aassetnote-io-resources-research-turning-bad-ssrf-to-good-ssrf-websphere-portal-cve-2021-27748.md)
- HTTPS-only filter bypassed by redirect to HTTP metadata [E3](https://bugbountylibrary.com/r/h1%3A1108418.md)
- Cross-protocol redirect deletes the SSRF agent, dropping the guard [E4](https://bugbountylibrary.com/r/blog%3Ablog-doyensec-com-2023-03-16-ssrf-remediation-bypass-html.md)
- Only 301/302 blocked; 303 See Other still followed [E5](https://bugbountylibrary.com/r/h1%3A508459.md)
- Redirect to gopher:// reaches arbitrary TCP services [E6](https://bugbountylibrary.com/r/h1%3A811136.md)
- Route segments map to a URL-fetching method with no scheme check [E7](https://bugbountylibrary.com/r/h1%3A895696.md)
- Kernel.Open plus host whitelist as the only defense [E8](https://bugbountylibrary.com/r/h1%3A1092230.md)

## Why fixes fail
Adding an SSRF agent filter was bypassed when a cross-protocol redirect deleted the agent [E4](https://bugbountylibrary.com/r/blog%3Ablog-doyensec-com-2023-03-16-ssrf-remediation-bypass-html.md). A host whitelist alone failed because a whitelisted domain ran an open redirect [E2](https://bugbountylibrary.com/r/blog%3Aassetnote-io-resources-research-turning-bad-ssrf-to-good-ssrf-websphere-portal-cve-2021-27748.md) and because the underlying client followed redirects to loopback [E8](https://bugbountylibrary.com/r/h1%3A1092230.md). Blocking redirects failed when only common status codes were covered [E5](https://bugbountylibrary.com/r/h1%3A508459.md).

## Impact and severity
Reached local repo contents, cloud metadata and IAM credentials, internal services, and arbitrary TCP (SMTP via gopher) [E6](https://bugbountylibrary.com/r/h1%3A811136.md). Worse when the fetcher reaches link-local metadata [E3](https://bugbountylibrary.com/r/h1%3A1108418.md) or when a whitelisted third-party domain can be pivoted through [E2](https://bugbountylibrary.com/r/blog%3Aassetnote-io-resources-research-turning-bad-ssrf-to-good-ssrf-websphere-portal-cve-2021-27748.md)[E8](https://bugbountylibrary.com/r/h1%3A1092230.md).

## Evidence
- E1: https://bugbountylibrary.com/r/h1%3A1685822.md
- E2: https://bugbountylibrary.com/r/blog%3Aassetnote-io-resources-research-turning-bad-ssrf-to-good-ssrf-websphere-portal-cve-2021-27748.md
- E3: https://bugbountylibrary.com/r/h1%3A1108418.md
- E4: https://bugbountylibrary.com/r/blog%3Ablog-doyensec-com-2023-03-16-ssrf-remediation-bypass-html.md
- E5: https://bugbountylibrary.com/r/h1%3A508459.md
- E6: https://bugbountylibrary.com/r/h1%3A811136.md
- E7: https://bugbountylibrary.com/r/h1%3A895696.md
- E8: https://bugbountylibrary.com/r/h1%3A1092230.md
