Api Key Exposure in Echo Go
How Api Key Exposure Manifests in Echo Go
Api key exposure in Echo Go typically occurs through several Echo Go-specific patterns. The most common is hardcoding API keys directly in Go source files, often in configuration structs or environment variable assignments. For example:
package main
import "github.com/labstack/echo/v4"
func main() {
e := echo.New()
// HARDCODED API KEY - CRITICAL VULNERABILITY
apiKey := "sk-1234567890abcdef"
e.GET("/api/data", func(c echo.Context) error {
if c.Request().Header.Get("x-api-key") != apiKey {
return echo.NewHTTPError(401, "Unauthorized")
}
return c.JSON(200, map[string]string{"message": "data"})
})
e.Start(":8080")
}
Another Echo Go-specific pattern is logging sensitive data. Echo's default logger can inadvertently log API keys when included in request contexts:
e.Use(middleware.Logger())
// THIS LOGS THE API KEY TO CONSOLE/LOG FILES
e.GET("/api/data", func(c echo.Context) error {
apiKey := c.Request().Header.Get("x-api-key")
log.Printf("Processing request with API key: %s", apiKey) // EXPOSURE HERE
return c.JSON(200, map[string]string{"message": "data"})
})
Echo Go's middleware chain can also propagate API keys insecurely. When using custom middleware that stores API keys in request contexts:
func apiKeyMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
apiKey := c.Request().Header.Get("x-api-key")
c.Set("apiKey", apiKey) // STORED IN CONTEXT - POTENTIAL LEAK
return next(c)
}
}
// Later middleware or handlers might inadvertently expose it
func debugMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
apiKey, exists := c.Get("apiKey").(string)
if exists {
log.Printf("Debug: API key present: %s", apiKey) // EXPOSURE
}
return next(c)
}
}
Echo Go applications also frequently expose API keys through error messages. When authentication fails, Echo's default error handling might include sensitive header information:
e.GET("/api/data", func(c echo.Context) error {
apiKey := c.Request().Header.Get("x-api-key")
if apiKey != "valid-key" {
return echo.NewHTTPError(401, "Invalid API key: "+apiKey) // EXPOSES INVALID KEY
}
return c.JSON(200, map[string]string{"message": "data"})
})
Echo Go-Specific Detection
Detecting API key exposure in Echo Go applications requires both static analysis and runtime scanning. For static analysis, middleBrick's CLI tool can scan your Go source code for hardcoded credentials:
npm install -g middlebrick
middlebrick scan ./my-echo-app --type go
middleBrick specifically looks for Echo Go patterns including:
- Hardcoded strings in configuration structs
- API key patterns in source files (sk-*, pk-*, api keys)
- Echo context usage that might expose sensitive data
- Middleware chains that store credentials insecurely
For runtime detection, middleBrick can scan your running Echo Go API endpoints:
middlebrick scan https://your-echo-app.com/api --type echo-go
This black-box scan tests for:
- API key exposure in HTTP headers and responses
- Echo Go-specific error messages that leak credentials
- Middleware vulnerabilities that might expose API keys
- Echo Go's default logging behavior and its potential to log sensitive data
Echo Go developers can also use middleBrick's GitHub Action for CI/CD integration:
name: Security Scan
on: [push, pull_request]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run middleBrick Scan
uses: middlebrick/middlebrick-action@v1
with:
target: ./api
type: echo-go
fail-on-severity: high
Echo Go's built-in middleware can help detect API key exposure during development. The Echo Logger middleware with custom formatters can be configured to redact sensitive data:
e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
Format: "${time_rfc3339} ${status} ${method} ${uri} ${latency_human} ${error}\n",
Output: io.Discard, // Temporarily disable logging to check for exposure
}))
Echo Go-Specific Remediation
Remediating API key exposure in Echo Go requires using the framework's native features for secure credential management. The primary solution is using Echo Go's configuration system with environment variables:
package main
import (
"os"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
func main() {
e := echo.New()
// SECURE: Load from environment variable
apiKey := os.Getenv("API_KEY")
if apiKey == "" {
log.Fatal("API_KEY environment variable not set")
}
// Use Echo's middleware for authentication
e.Use(middleware.KeyAuthWithConfig(middleware.KeyAuthConfig{
KeyLookup: "header:X-API-Key",
Validator: func(key string, c echo.Context) (bool, error) {
return key == apiKey, nil
},
// CRITICAL: Prevent key from being logged
ContextKey: "",
}))
e.GET("/api/data", func(c echo.Context) error {
return c.JSON(200, map[string]string{"message": "secure data"})
})
e.Start(":8080")
}
Echo Go's KeyAuth middleware is specifically designed to handle API keys securely without exposing them in logs or contexts. For more complex scenarios, use Echo's JWT middleware:
e.Use(middleware.JWTWithConfig(middleware.JWTConfig{
SigningKey: []byte(os.Getenv("JWT_SECRET")),
// JWT tokens are self-contained, no need to store raw keys
}))
For Echo Go applications that need to handle multiple API keys or key rotation, implement a secure key store:
type secureKeyStore struct {
keys map[string]bool
}
func (s *secureKeyStore) isValid(key string) bool {
// Check without logging or exposing the key
_, exists := s.keys[key]
return exists
}
// Usage in middleware
e.Use(middleware.KeyAuthWithConfig(middleware.KeyAuthConfig{
KeyLookup: "header:X-API-Key",
Validator: func(key string, c echo.Context) (bool, error) {
store := c.Get("keyStore").(*secureKeyStore)
return store.isValid(key), nil
},
}))
Echo Go's error handling can be configured to prevent API key exposure in error messages:
e.GET("/api/data", func(c echo.Context) error {
apiKey := c.Request().Header.Get("x-api-key")
if !isValidKey(apiKey) {
// DO NOT include the key in the error message
return echo.NewHTTPError(401, "Invalid API key")
}
return c.JSON(200, map[string]string{"message": "data"})
})