HIGH ssrfchi

Ssrf in Chi

How SSRF Manifests in Chi

Server-Side Request Forgery (SSRF) in Chi manifests when an API endpoint accepts user-controlled URLs and makes outbound HTTP requests without proper validation. In Chi applications, this commonly occurs in webhook handlers, proxy endpoints, and external API integrations.

The most frequent attack pattern involves endpoint handlers that accept a URL parameter and use Go's http.Client to make requests. Attackers can supply internal network addresses like localhost:8080, 192.168.1.1, or cloud metadata endpoints like http://169.254.169.254/latest/meta-data/. Chi's flexible routing and parameter handling makes it easy to inadvertently create SSRF vulnerabilities when processing these inputs.

// Vulnerable Chi route
router.Post("/webhook", func(w http.ResponseWriter, r *http.Request) {
    var payload struct {
        URL string `json:"url"`
    }
    
    if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
        http.Error(w, "Invalid payload", 400)
        return
    }
    
    // SSRF vulnerability - no URL validation
    resp, err := http.Get(payload.URL)
    if err != nil {
        http.Error(w, err.Error(), 500)
        return
    }
    defer resp.Body.Close()
    
    w.WriteHeader(200)
})

Another Chi-specific manifestation occurs with path parameters that contain URLs. Chi's {param} syntax captures everything until the next slash, but attackers can use encoded characters or special formats to bypass naive validation:

// Vulnerable route with path parameter
router.Get("/proxy/{url}", func(w http.ResponseWriter, r *http.Request) {
    url := chi.URLParam(r, "url")
    
    // SSRF here - attacker can use localhost, internal IPs, etc.
    resp, err := http.Get("https://" + url)
    if err != nil {
        http.Error(w, err.Error(), 500)
        return
    }
    defer resp.Body.Close()
    
    w.WriteHeader(resp.StatusCode)
})

Cloud-specific SSRF attacks target metadata services. In AWS, http://169.254.169.254 provides instance credentials and configuration data. In Azure, http://169.254.169.254/metadata/instance serves similar information. Chi applications running in cloud environments are particularly vulnerable if they proxy requests without validation.

Chi-Specific Detection

Detecting SSRF in Chi applications requires both static analysis and dynamic testing. Static analysis involves reviewing route handlers that accept URL parameters or make outbound HTTP requests. Look for patterns where user input flows directly into http.Client calls without validation.

middleBrick's black-box scanning approach is particularly effective for Chi applications since it tests the actual running API without requiring source code access. The scanner automatically detects SSRF vulnerabilities by attempting requests to internal network ranges, localhost, and cloud metadata endpoints.

Key detection patterns for Chi applications:

  • Route handlers accepting URL parameters ({url}, {target}, etc.)
  • JSON request bodies containing URL fields
  • Query parameters used for external requests
  • Webhook handlers that forward requests to user-supplied destinations
  • Proxy endpoints that relay external content

middleBrick tests these patterns with 12 parallel security checks, including SSRF-specific probes that attempt requests to:

http://localhost:8080
http://127.0.0.1
http://169.254.169.254/latest/meta-data/
http://169.254.169.254/metadata/instance
http://192.168.1.1
http://[::1]
http://example.com/redirect-to-internal

The scanner's LLM/AI security module also detects SSRF in AI-specific endpoints, testing for metadata service access through AI model interfaces and tool-calling mechanisms that might inadvertently expose internal services.

For continuous monitoring, the middleBrick GitHub Action can be configured to scan Chi APIs in CI/CD pipelines, failing builds if SSRF vulnerabilities are detected in staging environments before production deployment.

Chi-Specific Remediation

Remediating SSRF in Chi applications requires a defense-in-depth approach combining input validation, allowlist filtering, and safe request handling. The most effective strategy is to implement strict allowlist validation for all user-supplied URLs.

First, validate the scheme and host using Go's url.URL parsing:

import (
    "net/url"
    "strings"
)

// Allowlist of permitted domains
var allowedDomains = map[string]bool{
    "api.example.com": true,
    "webhook.example.com": true,
    "trusted-service.com": true,
}

func validateURL(rawURL string) (*url.URL, error) {
    parsed, err := url.Parse(rawURL)
    if err != nil {
        return nil, err
    }
    
    // Block private IP ranges and localhost
    if isPrivateIP(parsed.Hostname()) {
        return nil, errors.New("private IP addresses not allowed")
    }
    
    // Block cloud metadata services
    if isMetadataService(parsed.Hostname()) {
        return nil, errors.New("metadata service access denied")
    }
    
    // Validate against allowlist
    if !allowedDomains[parsed.Hostname()] {
        return nil, errors.New("domain not in allowlist")
    }
    
    return parsed, nil
}

func isPrivateIP(host string) bool {
    // Check for private IP ranges, localhost, etc.
    return strings.HasPrefix(host, "127.") || 
           strings.HasPrefix(host, "10.") || 
           strings.HasPrefix(host, "172.16") || 
           strings.HasPrefix(host, "192.168.") ||
           strings.HasPrefix(host, "::1")
}

func isMetadataService(host string) bool {
    return host == "169.254.169.254" || 
           host == "169.254.169.254" ||
           strings.Contains(host, "169.254")
}

Apply this validation in your Chi route handlers:

router.Post("/webhook", func(w http.ResponseWriter, r *http.Request) {
    var payload struct {
        URL string `json:"url"`
    }
    
    if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
        http.Error(w, "Invalid payload", 400)
        return
    }
    
    // Validate URL before use
    validatedURL, err := validateURL(payload.URL)
    if err != nil {
        http.Error(w, "Invalid URL: "+err.Error(), 400)
        return
    }
    
    // Make the request with timeout
    client := &http.Client{
        Timeout: 10 * time.Second,
    }
    
    resp, err := client.Get(validatedURL.String())
    if err != nil {
        http.Error(w, err.Error(), 500)
        return
    }
    defer resp.Body.Close()
    
    w.WriteHeader(200)
})

For proxy functionality, implement content-type detection and size limits to prevent SSRF exploitation through large responses or malicious content:

router.Get("/safe-proxy/{url}", func(w http.ResponseWriter, r *http.Request) {
    rawURL := chi.URLParam(r, "url")
    validatedURL, err := validateURL(rawURL)
    if err != nil {
        http.Error(w, "Invalid URL", 400)
        return
    }
    
    client := &http.Client{
        Timeout: 10 * time.Second,
    }
    
    resp, err := client.Get(validatedURL.String())
    if err != nil {
        http.Error(w, err.Error(), 500)
        return
    }
    defer resp.Body.Close()
    
    // Limit response size
    body, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1024*1024)) // 1MB limit
    if err != nil {
        http.Error(w, "Response too large", 500)
        return
    }
    
    // Set appropriate content-type
    w.Header().Set("Content-Type", resp.Header.Get("Content-Type"))
    w.Write(body)
})

middleBrick's CLI tool can verify these fixes by scanning your Chi application endpoints after remediation, ensuring SSRF vulnerabilities are properly addressed before deployment.

Related CWEs: ssrf

CWE IDNameSeverity
CWE-918Server-Side Request Forgery (SSRF) CRITICAL
CWE-441Unintended Proxy or Intermediary (Confused Deputy) HIGH

Frequently Asked Questions

How does SSRF differ in Chi compared to other Go frameworks?
Chi's simplicity and minimal middleware stack means SSRF vulnerabilities often appear more directly in route handlers. Unlike Gin or Echo which have more built-in validation middleware, Chi requires explicit security implementations. The framework's clean parameter handling with chi.URLParam() can make it easier to accidentally expose internal services if validation isn't properly implemented.
Can middleBrick detect SSRF in Chi applications running in containers?
Yes, middleBrick's black-box scanning works regardless of deployment architecture. The scanner tests the actual API endpoints without requiring access to the container environment, source code, or credentials. It can detect SSRF attempts against internal container networks, localhost services, and cloud metadata endpoints that Chi applications might inadvertently expose.