LocalhostOnlyRedirects returns an http.Client.CheckRedirect that limits the redirect chain to maxHops AND requires every redirect target to be an http://localhost URL. This prevents a localhost service from redirecting to internal network addresses (e.g. cloud metadata endpoints), which would bypass
(maxHops int)
| 254 | // to internal network addresses (e.g. cloud metadata endpoints), which |
| 255 | // would bypass SSRF protection. |
| 256 | func LocalhostOnlyRedirects(maxHops int) func(*http.Request, []*http.Request) error { |
| 257 | return func(req *http.Request, via []*http.Request) error { |
| 258 | if len(via) >= maxHops { |
| 259 | return fmt.Errorf("stopped after %d redirects", maxHops) |
| 260 | } |
| 261 | if req.URL.Scheme != "http" || req.URL.Hostname() != "localhost" { |
| 262 | return fmt.Errorf("refusing redirect to non-localhost URL %q", req.URL.Redacted()) |
| 263 | } |
| 264 | return nil |
| 265 | } |
| 266 | } |
no outgoing calls