|
| 1 | +```toml |
| 2 | +[advisory] |
| 3 | +id = "RUSTSEC-0000-0000" |
| 4 | +package = "reqwest" |
| 5 | +date = "2026-02-22" |
| 6 | +url = "https://github.com/seanmonstar/reqwest/issues/2260" |
| 7 | +categories = ["denial-of-service"] |
| 8 | +keywords = ["ssrf", "redirect", "private-network", "metadata"] |
| 9 | + |
| 10 | +[versions] |
| 11 | +patched = [] |
| 12 | +unaffected = [] |
| 13 | +``` |
| 14 | + |
| 15 | +# reqwest: SSRF via Default Redirect Policy Following to Private Networks |
| 16 | + |
| 17 | +reqwest follows up to 10 redirects by default via `redirect::Policy::default()`. |
| 18 | +This policy does not filter redirect targets against private/internal IP ranges |
| 19 | +(RFC 1918, link-local, loopback, cloud metadata endpoints). |
| 20 | + |
| 21 | +An attacker who can influence a URL fetched by a server-side application using |
| 22 | +reqwest can redirect the request to internal services (e.g., AWS/GCP/Azure |
| 23 | +metadata at 169.254.169.254, localhost services, internal network hosts), |
| 24 | +enabling Server-Side Request Forgery (SSRF, CWE-918). |
| 25 | + |
| 26 | +This is a well-known SSRF attack class that browsers mitigate with private |
| 27 | +network access controls, but reqwest provides no equivalent built-in protection. |
| 28 | + |
| 29 | +Any server-side application fetching user-controlled URLs with the default |
| 30 | +redirect policy is vulnerable. |
| 31 | + |
| 32 | +## Mitigation |
| 33 | + |
| 34 | +Use a custom redirect policy that validates redirect targets: |
| 35 | + |
| 36 | +```rust |
| 37 | +let policy = reqwest::redirect::Policy::custom(|attempt| { |
| 38 | + let url = attempt.url(); |
| 39 | + if is_private_ip(url) { |
| 40 | + attempt.stop() |
| 41 | + } else { |
| 42 | + attempt.follow() |
| 43 | + } |
| 44 | +}); |
| 45 | +``` |
0 commit comments