package proxy import ( "fmt" "net" "net/url" "strings" ) var blockedHosts = map[string]struct{}{ "169.254.169.254": {}, "metadata.google.internal": {}, } // ValidateURL applies MVP SSRF basics. Week 2 should add configurable CIDR // deny-lists and DNS-rebinding protection before exposing this beyond localhost. func ValidateURL(raw string) (*url.URL, error) { u, err := url.Parse(raw) if err != nil { return nil, fmt.Errorf("invalid url: %w", err) } if u.Scheme != "http" && u.Scheme != "https" { return nil, fmt.Errorf("only http/https schemes are allowed") } if u.Hostname() == "" { return nil, fmt.Errorf("url host is required") } host := strings.ToLower(strings.TrimSuffix(u.Hostname(), ".")) if _, blocked := blockedHosts[host]; blocked { return nil, fmt.Errorf("blocked metadata host") } if ip := net.ParseIP(host); ip != nil && ip.Equal(net.ParseIP("169.254.169.254")) { return nil, fmt.Errorf("blocked metadata address") } return u, nil }