Ssrf in Echo Go with Api Keys
Ssrf in Echo Go with Api Keys — how this specific combination creates or exposes the vulnerability
Server-Side Request Forgery (SSRF) in an Echo Go service that uses API keys for external authorization can occur when user-supplied input is used to construct HTTP requests to downstream services. In this scenario, the API key is typically stored as a server-side credential and passed by the backend when calling external APIs. If the application accepts a URL from the client and forwards it using an http.Client with the API key attached (e.g., via an Authorization header or a query parameter), an attacker can force the server to make arbitrary internal or external requests.
For example, an attacker might provide a URL pointing to the metadata service (http://169.254.169.254/latest/meta-data/) or an internal Kubernetes service (http://kubernetes.default.svc), bypassing egress firewall rules because the request originates from the trusted backend. The API key itself is not leaked in this case, but the server’s trust relationship and credentials are abused to reach destinations that should be inaccessible. This pattern is common in services that integrate with third-party APIs and use static keys for outbound authentication.
In Echo Go, a typical handler might extract a target URL and an API key from request parameters or headers, then create a new request with the key added to the headers. If the target URL is not strictly validated or restricted, the handler can be tricked into making requests to internal endpoints. The vulnerability is not in how the API key is stored, but in how the destination URL is determined and used. Attack patterns such as probing internal metadata endpoints or SSRF via cloud instance metadata services are realistic threat scenarios that this combination enables.
middleBrick detects SSRF by tracing how user-controlled input flows into outbound HTTP calls and identifying whether internal or sensitive endpoints are reachable. This is one of the 12 parallel security checks, ensuring that SSRF is evaluated alongside other risks such as Authentication and Data Exposure. The scanner tests whether an API can be tricked into interacting with internal services without requiring authentication, highlighting the absence of network-level restrictions or URL allowlisting.
Api Keys-Specific Remediation in Echo Go — concrete code fixes
To remediate SSRP when using API keys in Echo Go, avoid using user-supplied URLs for outbound requests. If you must accept target destinations, enforce strict allowlisting of hostnames and paths, and resolve hostnames to specific IP ranges that are explicitly permitted. Do not forward requests to internal or cloud metadata endpoints. Additionally, avoid adding API keys to requests that are constructed from uncontrolled inputs.
Below are example implementations that demonstrate secure handling of API keys in Echo Go.
package main
import (
"net/http"
"strings"
"github.com/labstack/echo/v4"
)
// Secure: API key is used only for authorized, predefined endpoints
type ExternalService struct {
BaseURL string
APIKey string
}
func (s *ExternalService) CallAllowedEndpoint(c echo.Context) error {
// Only allow a specific, known endpoint; do not use raw user URL
req, err := http.NewRequest(http.MethodGet, s.BaseURL+"/v1/status", nil)
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "failed to create request")
}
req.Header.Set("Authorization", "Bearer "+s.APIKey)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return echo.NewHTTPError(http.StatusBadGateway, "external service error")
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return echo.NewHTTPError(resp.StatusCode, "unexpected status")
}
return c.JSON(http.StatusOK, map[string]string{"status": "ok"})
}
// Insecure: constructing request URL from user input — vulnerable to SSRF
func (s *ExternalService) CallUserURL(c echo.Context) error {
userURL := c.QueryParam("url")
if userURL == "" {
return echo.NewHTTPError(http.StatusBadRequest, "url parameter required")
}
// Dangerous: attacker can set url=http://169.254.169.254/latest/meta-data/
req, err := http.NewRequest(http.MethodGet, userURL, nil)
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "invalid url")
}
req.Header.Set("Authorization", "Bearer "+s.APIKey)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return echo.NewHTTPError(http.StatusBadGateway, "request failed")
}
defer resp.Body.Close()
return c.JSONRawMessage(resp.StatusCode, nil) // naive passthrough
}
func main() {
e := echo.New()
svc := &ExternalService{
BaseURL: "https://api.external.com",
APIKey: "example-key-123",
}
e.GET("/secure", svc.CallAllowedEndpoint)
// Do not expose an endpoint like this in production
// e.GET("/insecure", svc.CallUserURL)
e.Logger.Fatal(e.Start(":8080"))
}
Key remediation points:
- Do not construct outbound URLs from user-controlled input.
- If dynamic endpoints are required, validate the hostname against an allowlist and reject private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) and cloud metadata addresses (169.254.169.254, 100.100.100.200).
- Keep API keys in server-side configuration and avoid including them in requests that are built from untrusted data.
- Use environment variables or a secrets manager for API keys, and rotate them regularly.
middleBrick’s OpenAPI/Swagger analysis can reveal whether outbound call patterns rely on user-supplied URLs, and the scanner’s runtime checks validate whether SSRF paths are reachable. By combining specification review with active testing, the tool highlights missing input validation and overly permissive network access without making changes to your code.
Related CWEs: ssrf
| CWE ID | Name | Severity |
|---|---|---|
| CWE-918 | Server-Side Request Forgery (SSRF) | CRITICAL |
| CWE-441 | Unintended Proxy or Intermediary (Confused Deputy) | HIGH |