Cors Wildcard in Gorilla Mux with Basic Auth
Cors Wildcard in Gorilla Mux with Basic Auth — how this specific combination creates or exposes the vulnerability
A CORS wildcard (Access-Control-Allow-Origin: *) combined with Basic Authentication in Gorilla Mux can unintentionally expose protected endpoints to any origin. When middleware sets an unrestricted Access-Control-Allow-Origin header while also requiring Basic Auth, browsers may still present credentials (e.g., Authorization header) to the wildcard origin, enabling cross-origin requests that appear authenticated to the client-side JavaScript. This violates the principle that wildcard origins should not be used when credentials are involved. In Gorilla Mux, routes often rely on handler wrappers that add CORS headers without inspecting whether authentication is required. If the route uses Basic Auth via a custom Authorization: Basic check and the CORS middleware adds *, an attacker can craft a web page that sends authenticated requests from a different origin, leveraging the browser’s CORS-preflight logic to bypass same-origin policy expectations.
For example, a route defined with mux.HandleFunc("/api/admin", adminHandler).Methods("GET") might use a Basic Auth wrapper that validates credentials. If a CORS handler sets Access-Control-Allow-Origin: * and Access-Control-Allow-Credentials: true, a malicious site can invoke fetch('/api/admin', { credentials: 'include' }) from any domain. The preflight request will include the Authorization header, and if the server responds with the wildcard origin plus credentials allowed, the attacker can read the response, leading to data exposure or unauthorized actions. This pattern is especially risky when the Basic Auth credentials are static or reused across services, as the wildcard effectively grants any origin access to the authenticated session.
Additionally, preflight requests (OPTIONS) sent by browsers will also receive the wildcard origin header, which can lead to insecure caching or logging of authentication headers in intermediate systems. Gorilla Mux does not inherently enforce origin validation; it is the responsibility of the developer to ensure that CORS configuration aligns with the authentication mechanism. Combining a wildcard with Basic Auth creates a scenario where the server implicitly trusts any origin to participate in the authenticated session, undermining the confidentiality and integrity guarantees of the Basic Authentication scheme.
Basic Auth-Specific Remediation in Gorilla Mux — concrete code fixes
To mitigate CORS misconfiguration with Basic Auth in Gorilla Mux, explicitly define allowed origins instead of using a wildcard, and conditionally set CORS headers based on the presence and validity of credentials. Below are two concrete approaches: a strict origin allowlist and a preflight-safe handler that avoids exposing credentials to unauthorized origins.
1. Explicit origin allowlist with Basic Auth
Define a middleware that checks the Origin header against a list of trusted origins and sets CORS headers only when the origin is permitted. This ensures that even with Basic Auth, credentials are not shared with untrusted domains.
import (
"net/http"
"github.com/gorilla/mux"
)
var allowedOrigins = map[string]bool{
"https://example.com": true,
"https://app.example.com": true,
}
func corsMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
origin := r.Header.Get("Origin")
if allowedOrigins[origin] {
w.Header().Set("Access-Control-Allow-Origin", origin)
w.Header().Set("Access-Control-Allow-Credentials", "true")
}
if r.Method == "OPTIONS" {
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Authorization, Content-Type")
w.WriteHeader(http.StatusOK)
return
}
next.ServeHTTP(w, r)
})
}
func basicAuth(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
user, pass, ok := r.BasicAuth()
if !ok || user != "admin" || pass != "s3cr3t" {
w.Header().Set("WWW-Authenticate", `Basic realm="restricted", charset="UTF-8"`)
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
})
}
func adminHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Admin area"))
}
func main() {
r := mux.NewRouter()
r.HandleFunc("/api/admin", adminHandler).Methods("GET")
wrapped := corsMiddleware(basicAuth(r))
http.ListenAndServe(":8080", wrapped)
}
2. Preflight-safe handler with conditional CORS
Handle OPTIONS requests separately and avoid setting authentication headers in responses to preflight requests. This prevents browsers from caching unauthorized CORS configurations and keeps Basic Auth challenges isolated to actual requests.
func safeCORS(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
origin := r.Header.Get("Origin")
if origin == "https://example.com" {
w.Header().Set("Access-Control-Allow-Origin", origin)
w.Header().Set("Access-Control-Allow-Credentials", "true")
}
if r.Method == "OPTIONS" {
w.Header().Set("Access-Control-Allow-Methods", "GET")
w.Header().Set("Access-Control-Allow-Headers", "Authorization")
w.WriteHeader(http.StatusNoContent)
return
}
next.ServeHTTP(w, r)
})
}
func main() {
r := mux.NewRouter()
r.HandleFunc("/api/data", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("protected data"))
}).Methods("GET")
http.ListenAndServe(":8080", safeCORS(r))
}
These patterns ensure that CORS headers are tightly coupled with the authentication mechanism, reducing the risk of cross-origin abuse while preserving legitimate access from trusted origins.
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 |