CRITICAL ssrf server sideecho gobearer tokens

Ssrf Server Side in Echo Go with Bearer Tokens

Ssrf Server Side in Echo Go with Bearer Tokens — how this specific combination creates or exposes the vulnerability

Server Side Request Forgery (SSRF) in an Echo Go service that uses Bearer Tokens can occur when user-supplied input is used to construct HTTP requests on the server and that input is not strictly validated or constrained. If an endpoint accepts a URL or host parameter and uses it to call downstream services, an attacker can force the server to make internal or external requests that include sensitive Bearer Tokens the process possesses.

In Echo Go, a common pattern is to read a token from a header or a request parameter and then pass it to an HTTP client when making outbound calls. If the target URL is also user-controlled, an attacker can supply a malicious destination that causes the server to relay its outbound requests—along with any attached Authorization headers—toward internal metadata services (e.g., http://169.254.169.254), cloud instance metadata endpoints, or internal APIs that trust the server’s token.

For example, consider an Echo Go handler that forwards a request to a user-provided URL while attaching a service Bearer Token:

package main

import (
    "net/http"
    "github.com/labstack/echo/v4"
    "github.com/labstack/echo/v4/middleware"
)

func main() {
    e := echo.New()
    e.Use(middleware.Logger())
    e.POST("/forward", func(c echo.Context) error {
        target := c.FormValue("url")
        token := c.Get("token").(string) // Assume token set from auth middleware
        req, _ := http.NewRequest(http.MethodGet, target, nil)
        req.Header.Set("Authorization", "Bearer "+token)
        resp, err := http.DefaultClient.Do(req)
        if err != nil {
            return c.String(http.StatusInternalServerError, err.Error())
        }
        defer resp.Body.Close()
        return c.JSONBlob(http.StatusOK, nil)
    })
    e.Start(":8080")
}

In this pattern, if target is not validated, an attacker can supply an internal address such as http://169.254.169.254/latest/meta-data/iam/security-credentials/ and the server will make a request to the instance metadata endpoint with its Bearer Token, effectively leaking the token. Even with a seemingly safe prefix like https://api.partner.com, an attacker might use a malicious hostname that resolves internally or use SSRF to bypass allowlists via URL encoding, homograph tricks, or schema confusion (e.g., http://google.com@169.254.169.254).

Additionally, if the Bearer Token is extracted from a request and reused without scoping or audience validation, SSRF becomes more impactful because the downstream service sees requests that appear to originate from a legitimate, authorized principal. This can lead to data exposure, privilege escalation against internal APIs, or lateral movement within a private network. The risk is compounded when services use long-lived tokens or shared secrets that are not rotated frequently.

middleBrick scans can surface such SSRF vectors by analyzing the unauthenticated attack surface and cross-referencing runtime behavior with the OpenAPI spec, identifying endpoints that accept URLs and pass Authorization headers without strict allowlisting or input validation.

Bearer Tokens-Specific Remediation in Echo Go — concrete code fixes

To mitigate SSRF when using Bearer Tokens in Echo Go, constrain outbound destinations and avoid blindly reusing incoming tokens. Prefer allowlisting known, verified hosts and use a dedicated outbound client with timeouts and redirect handling disabled or carefully controlled.

Instead of forwarding user input directly, validate the target host and scheme:

package main

import (
    "errors"
    "net"
    "net/http"
    "net/url"
    "strings"

    "github.com/labstack/echo/v4"
    "github.com/labstack/echo/v4/middleware"
)

var allowedHosts = map[string]bool{
    "api.partner.com": true,
    "api.vendor.io":    true,
}

func isValidTarget(raw string) error {
    u, err := url.Parse(raw)
    if err != nil {
        return errors.New("invalid url")
    }
    if u.Scheme != "https" {
        return errors.New("only https allowed")
    }
    host := strings.ToLower(u.Hostname())
    if !allowedHosts[host] {
        return errors.New("host not allowed")
    }
    // optionally: ensure no internal IPs
    if ip := net.ParseIP(host); ip != nil {
        if ip.IsPrivate() || ip.IsLoopback() || ip.IsLinkMulticast() {
            return errors.New("internal host not allowed")
        }
    }
    return nil
}

func main() {
    e := echo.New()
    e.Use(middleware.Logger())
    e.POST("/forward", func(c echo.Context) error {
        target := c.FormValue("url")
        if err := isValidTarget(target); err != nil {
            return c.String(http.StatusBadRequest, "invalid target: "+err.Error())
        }
        token := c.Get("token").(string)
        req, err := http.NewRequest(http.MethodGet, target, nil)
        if err != nil {
            return c.String(http.StatusBadRequest, "invalid request")
        }
        req.Header.Set("Authorization", "Bearer "+token)
        // Use a client with timeouts and no redirects to reduce risk
        client := &http.Client{
            CheckRedirect: func(req *http.Request, via []*http.Request) error {
                return http.ErrUseLastResponse
            },
        }
        resp, err := client.Do(req)
        if err != nil {
            return c.String(http.StatusInternalServerError, err.Error())
        }
        defer resp.Body.Close()
        return c.JSONBlob(http.StatusOK, nil)
    })
    e.Start(":8080")
}

If you need to call multiple downstream services, scope the Bearer Token to a specific audience and avoid reusing the same token across different contexts. Consider using short-lived tokens retrieved from a secure vault instead of long-lived secrets stored in application memory. The middleware approach can also enforce authentication centrally, ensuring that the token present in the request is not inadvertently propagated to outbound calls when not required.

In CI/CD and development workflows, you can use the middleBrick CLI to scan your Echo Go service from the terminal: middlebrick scan <url>. The GitHub Action can add API security checks to your pipeline, failing builds if risk scores drop below your chosen threshold, while the MCP Server enables scanning APIs directly from your AI coding assistant within the IDE.

Frequently Asked Questions

Can SSRF with Bearer Tokens lead to token leakage even if the service uses HTTPS?
Yes. SSRF targets are not determined by the transport security (HTTPS). If the server forwards requests to an internal or attacker-controlled endpoint, the Bearer Token included in the Authorization header can be captured or abused regardless of TLS. The key mitigation is destination allowlisting and avoiding token reuse across untrusted targets.
Does middleBrick fix SSRF or token leakage findings?
middleBrick detects and reports findings with remediation guidance, but it does not fix, patch, block, or remediate. It provides prioritized findings and actionable guidance so you can address SSRF and token handling issues in your code.