Token Leakage in Echo Go
How Token Leakage Manifests in Echo Go
Token leakage in Echo Go occurs when authentication tokens, API keys, or session identifiers are inadvertently exposed through Echo Go's response mechanisms. This manifests in several Echo Go-specific patterns:
// Vulnerable Echo Go handler - token in response body
func getUserProfile(c echo.Context) error {
token := c.Request().Header.Get("Authorization")
userID := extractUserIDFromToken(token)
user := db.GetUser(userID)
return c.JSON(http.StatusOK, map[string]interface{}{
"user": user,
"auth_token": token, // TOKEN LEAKAGE
})
}
The most common Echo Go token leakage patterns include:
- Echo context dumping: Using c.JSON() or c.String() to return entire context objects that contain sensitive headers
- Error response exposure: Returning error messages that include token fragments or stack traces with authentication data
- Echo middleware chaining: Middleware that passes context through multiple handlers, each potentially exposing token data
- Echo validator responses: Validation error messages that include original request data with tokens
Echo Go's middleware architecture creates unique token leakage opportunities. Consider this pattern:
// Vulnerable Echo Go middleware chain
func authMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
token := c.Request().Header.Get("Authorization")
c.Set("user_token", token) // STORED IN CONTEXT
return next(c)
}
}
func profileHandler(c echo.Context) error {
token := c.Get("user_token").(string)
// Some processing...
return c.JSON(http.StatusOK, map[string]interface{}{
"token_used": token, // EXPOSED TO CLIENT
})
}
Echo Go's JSON binding and validation also contribute to token leakage:
type LoginRequest struct {
Username string `json:"username" validate:"required"`
Password string `json:"password" validate:"required"`
}
func loginHandler(c echo.Context) error {
var req LoginRequest
if err := c.Bind(&req); err != nil {
return c.JSON(http.StatusBadRequest, map[string]interface{}{
"error": err.Error(), // MAY INCLUDE SENSITIVE DATA
"request": c.Request().Header, // TOKEN EXPOSURE
})
}
return c.JSON(http.StatusOK, map[string]interface{}{
"token": generateJWT(req.Username), // OK
})
}
Echo Go-Specific Detection
Detecting token leakage in Echo Go requires understanding Echo's request lifecycle and context management. Here's how to identify these vulnerabilities:
// Detection function for Echo Go token leakage
func detectTokenLeakage(handler http.HandlerFunc) bool {
// Test if handler returns sensitive headers in response
req := httptest.NewRequest("GET", "/test", nil)
req.Header.Set("Authorization", "Bearer test-token-123")
rr := httptest.NewRecorder()
handler(rr, req)
// Check response body for token patterns
body := rr.Body.String()
if strings.Contains(body, "test-token-123") ||
strings.Contains(body, "Authorization") ||
strings.Contains(body, "Bearer") {
return true
}
return false
}
Echo Go's middleware structure requires specific detection approaches:
// Echo-specific token leakage detector
func scanEchoAppForTokenLeakage(e *echo.Echo) []string {
var leaks []string
e.Walk(func(routeInfo echo.RouteInfo) {
// Check if route handler might expose tokens
handlerName := runtime.FuncForPC(reflect.ValueOf(routeInfo.HandlerFunc).Pointer()).Name()
// Look for suspicious patterns in handler code
if strings.Contains(handlerName, "getToken") ||
strings.Contains(handlerName, "auth") {
leaks = append(leaks, fmt.Sprintf("Potential leak in %s", routeInfo.Path))
}
})
return leaks
}
Using middleBrick for Echo Go token leakage detection:
# Scan Echo Go API endpoint
middlebrick scan https://api.example.com/echo-go-endpoint
# Output shows token leakage findings:
# - Authentication Bypass: BOLA (Insecure Direct Object Reference)
# - Data Exposure: Token in response body
# - Severity: HIGH
# - Remediation: Remove sensitive data from API responses
middleBrick's Echo Go-specific detection includes:
- Scanning for Authorization header exposure in JSON responses
- Detecting Echo context dumping patterns
- Identifying middleware chains that pass sensitive data
- Checking for token reflection in error responses
Echo Go-Specific Remediation
Remediating token leakage in Echo Go requires Echo-specific patterns and best practices:
// Secure Echo Go handler - no token exposure
func getUserProfile(c echo.Context) error {
token := c.Request().Header.Get("Authorization")
userID := extractUserIDFromToken(token)
user := db.GetUser(userID)
// SAFE: Only return user data, no token exposure
return c.JSON(http.StatusOK, map[string]interface{}{
"user": user,
})
}
Echo Go's context management requires careful handling:
// Secure middleware pattern
func authMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
token := c.Request().Header.Get("Authorization")
// Validate token but DON'T store in context
claims, err := validateJWT(token)
if err != nil {
return echo.NewHTTPError(http.StatusUnauthorized, "Invalid token")
}
// Store only sanitized user ID
c.Set("user_id", claims.UserID)
return next(c)
}
}
func profileHandler(c echo.Context) error {
userID := c.Get("user_id").(string)
user := db.GetUser(userID)
return c.JSON(http.StatusOK, map[string]interface{}{
"user": user,
})
}
Echo Go error handling patterns for token safety:
// Secure error responses
func errorHandler(err error, c echo.Context) error {
var statusCode int
var message string
switch e := err.(type) {
case *echo.HTTPError:
statusCode = e.Code
message = e.Message.(string)
default:
statusCode = http.StatusInternalServerError
message = "Internal server error"
}
// NEVER include request headers or tokens
return c.JSON(statusCode, map[string]interface{}{
"error": message,
})
}
Echo Go validation with token safety:
type SecureRequest struct {
Data string `json:"data" validate:"required"`
}
func secureHandler(c echo.Context) error {
var req SecureRequest
if err := c.Bind(&req); err != nil {
// Safe error response - no token exposure
return echo.NewHTTPError(http.StatusBadRequest, "Invalid request format")
}
// Process request securely
return c.JSON(http.StatusOK, map[string]interface{}{
"status": "success",
})
}