GuardAPI Logo
GuardAPI

Fix SSRF (Server Side Request Forgery) in Gin

SSRF (Server Side Request Forgery) in Go/Gin applications occurs when an attacker controls the destination of a server-side HTTP request. This allows them to scan internal ports, exfiltrate cloud metadata (like AWS/GCP credentials), or pivot into internal microservices. In Gin, this usually happens when query parameters are piped directly into the net/http client without IP-level validation.

The Vulnerable Pattern

func ProxyHandler(c *gin.Context) {
	// DANGER: Taking a raw URL from the user and fetching it
	targetURL := c.Query("url")
resp, err := http.Get(targetURL)
if err != nil {
	c.JSON(500, gin.H{"error": "request failed"})
	return
}
defer resp.Body.Close()

data, _ := io.ReadAll(resp.Body)
c.Data(200, "application/octet-stream", data)

}

The Secure Implementation

To properly mitigate SSRF, you cannot rely on simple string blacklists. The secure implementation uses a custom 'net.Dialer' with a 'Control' function. This allows the server to validate the resolved IP address *after* DNS resolution but *before* the connection is established, preventing DNS Rebinding attacks. We explicitly block loopback (127.0.0.1), private ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), and link-local addresses (169.254.169.254). Additionally, we disable automatic redirects to ensure an attacker cannot redirect a 'safe' domain to an 'internal' IP.

func SecureProxyHandler(c *gin.Context) {
	rawURL := c.Query("url")
	parsedURL, err := url.Parse(rawURL)
	if err != nil || (parsedURL.Scheme != "http" && parsedURL.Scheme != "https") {
		c.AbortWithStatus(400)
		return
	}
// Define a hardened transport to block internal IP ranges
transport := &http.Transport{
	DialContext: (&net.Dialer{
		Timeout: 5 * time.Second,
		Control: func(network, address string, c syscall.RawConn) error {
			host, _, _ := net.SplitHostPort(address)
			ip := net.ParseIP(host)
			if ip != nil && (ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast() || ip.IsUnspecified()) {
				return fmt.Errorf("access to internal IP %s is blocked", host)
			}
			return nil
		},
	}).DialContext,
}

client := &http.Client{
	Transport: transport,
	Timeout:   10 * time.Second,
	CheckRedirect: func(req *http.Request, via []*http.Request) error {
		return http.ErrUseLastResponse // Block redirects to prevent bypass
	},
}

resp, err := client.Get(parsedURL.String())
if err != nil {
	c.AbortWithStatus(502)
	return
}
defer resp.Body.Close()
io.Copy(c.Writer, resp.Body)

}

System Alert • ID: 4712
Target: Gin API
Potential Vulnerability

Your Gin API might be exposed to SSRF (Server Side Request Forgery)

74% of Gin apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.

RUN FREE SECURITY DIAGNOSTIC
GuardLabs Engine: ONLINE

Free Tier • No Credit Card • Instant Report

Verified by Ghost Labs Security Team

This content is continuously validated by our automated security engine and reviewed by our research team. Ghost Labs analyzes over 500+ vulnerability patterns across 40+ frameworks to provide up-to-date remediation strategies.