Cors Wildcard in Echo Go with Bearer Tokens
Cors Wildcard in Echo Go with Bearer Tokens — how this specific combination creates or exposes the vulnerability
In Echo Go, using a CORS wildcard (*) together with Bearer token authentication creates a critical exposure because the wildcard allows credentials from any origin, which can unintentionally permit unauthorized cross-origin requests that include protected tokens. When WithAllowCredentials() is enabled alongside a wildcard, browsers may allow frontend JavaScript hosted on arbitrary external origins to include Authorization headers, effectively bypassing intended same-origin or explicit-origin policies.
Consider a typical Echo setup that mistakenly pairs a permissive CORS configuration with bearer middleware:
import (
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
func main() {
e := echo.New()
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
AllowOrigins: []string{"*"},
AllowMethods: []string{echo.GET, echo.POST, echo.OPTIONS},
AllowHeaders: []string{echo.HeaderAuthorization, echo.HeaderContentType},
AllowCredentials: true,
}))
e.Use(middleware.JWTWithConfig(middleware.JWTConfig{
SigningKey: []byte("secret"),
AuthScheme: "Bearer",
ContextKey: "user",
}))
e.GET("/profile", func(c echo.Context) error {
return c.JSON(200, "profile")
})
e.Logger().Fatal(e.Start(":8080"))
}
This configuration allows any origin to make authenticated requests with a Bearer token if the browser includes credentials. An attacker-controlled site can craft a request to /profile with an Authorization header captured via a compromised subdomain or malicious browser extension, leveraging the wildcard to sidestep origin checks. Because the wildcard permits credentials, the token is transmitted cross-origin, exposing it to potential leakage via logs, intermediaries, or insecure referrers.
The risk is amplified when token handling is inconsistent across services. If some endpoints validate audience or issuer strictly while others rely solely on signature verification, a wildcard-enabled CORS route can become a pivot point for token replay across origins. In red-team exercises, this pattern has been observed in misconfigured APIs where a frontend served from https://evil.com successfully calls /auth/me with a stolen Bearer token due to the permissive CORS setup.
To align with the principle of least privilege, CORS should specify exact origins and avoid * when credentials are required. Combining explicit origins with tightly scoped AllowHeaders and careful validation of the Origin header reduces the attack surface. The same caution applies to token scope: restrict Bearer tokens to the minimal required permissions and validate aud and iss on every API call.
Bearer Tokens-Specific Remediation in Echo Go — concrete code fixes
Remediation focuses on removing the wildcard for credentialed requests and tightening CORS to match the set of origins that legitimately require Bearer token access. The following example demonstrates a secure configuration where origins are explicitly listed and credentials are permitted only for those origins.
import (
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
func main() {
e := echo.New()
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
AllowOrigins: []string{
"https://app.yourdomain.com",
"https://staging.yourdomain.com",
},
AllowMethods: []string{echo.GET, echo.POST, echo.OPTIONS},
AllowHeaders: []string{echo.HeaderAuthorization, echo.HeaderContentType},
ExposeHeaders: []string{echo.HeaderContentType},
AllowCredentials: true,
MaxAge: 3600,
}))
e.Use(middleware.JWTWithConfig(middleware.JWTConfig{
SigningKey: []byte("your-32-byte-long-secret-key-here-123456"),
AuthScheme: "Bearer",
ContextKey: "user",
TokenLookup: "header:Authorization",
}))
e.GET("/profile", func(c echo.Context) error {
user := c.Get("user").(*middleware.JWTClaim)
return c.JSON(200, map[string]string{
"sub": user.Subject,
"iss": user.Issuer,
})
})
e.Logger().Fatal(e.Start(":8080"))
}
This configuration ensures that only listed origins can send requests with Authorization headers. Token validation is performed by the JWT middleware, which extracts the Bearer token from the Authorization header and verifies its signature, issuer, and audience. Developers should rotate signing keys periodically and store them outside of source code, for example via environment variables injected at runtime.
For additional defense, apply strict scope checks within handlers and reject tokens that do not carry the expected aud for the service. If you use the middleBrick CLI to scan this service, you can verify that CORS is not overly permissive and that Bearer handling follows best practices:
middlebrick scan https://api.yourservice.com/openapi.json
The dashboard and CLI outputs will highlight CORS misconfigurations and token-related findings, enabling you to refine origins and token validation logic before deploying to production.
Related CWEs: dataExposure
| CWE ID | Name | Severity |
|---|---|---|
| CWE-200 | Exposure of Sensitive Information | HIGH |
| CWE-209 | Error Information Disclosure | MEDIUM |
| CWE-213 | Exposure of Sensitive Information Due to Incompatible Policies | HIGH |
| CWE-215 | Insertion of Sensitive Information Into Debugging Code | MEDIUM |
| CWE-312 | Cleartext Storage of Sensitive Information | HIGH |
| CWE-359 | Exposure of Private Personal Information (PII) | HIGH |
| CWE-522 | Insufficiently Protected Credentials | CRITICAL |
| CWE-532 | Insertion of Sensitive Information into Log File | MEDIUM |
| CWE-538 | Insertion of Sensitive Information into Externally-Accessible File | HIGH |
| CWE-540 | Inclusion of Sensitive Information in Source Code | HIGH |
Frequently Asked Questions
Why is using a CORS wildcard with credentials considered risky in Echo Go APIs that use Bearer tokens?
What is a secure alternative to a CORS wildcard for an Echo Go service that requires Bearer token authentication?
AllowOrigins, enable AllowCredentials only for those origins, and restrict AllowHeaders to Authorization and necessary headers. Validate token claims such as aud and iss on every request.