Cors Wildcard in Gorilla Mux with Dynamodb
Cors Wildcard in Gorilla Mux with Dynamodb — how this specific combination creates or exposes the vulnerability
A CORS wildcard (*) in a Gorilla Mux router becomes a exposure vector when responses originate from or reference data stored in DynamoDB. With a wildcard, the Access-Control-Allow-Origin header is sent for every origin, which can unintentionally expose authenticated API responses that include sensitive DynamoDB payloads. If your handlers construct responses directly from DynamoDB query results and allow credentials via Access-Control-Allow-Credentials: true, browsers will deliver those responses to any site, enabling cross-origin data reads.
Consider a pattern where a handler queries a DynamoDB table and writes results into the response writer. With a wildcard CORS policy and credentials allowed, any webpage on any origin can make authenticated requests and read the returned item attributes, including potentially primary keys or sensitive metadata. This violates the principle of least privilege and maps to the OWASP API Top 10 API1:2023 – Broken Object Level Authorization when combined with BOLA/IDOR risks, because the broad CORS rule removes the same-origin check that would otherwise limit exposure.
In a real-world scenario, an endpoint like /items/{id} fetches an item from DynamoDB by primary key. If CORS permits all origins and the response includes an Access-Control-Allow-Origin: * header along with Access-Control-Allow-Credentials: true, a malicious site can embed a script that calls this endpoint on behalf of an authenticated user. The browser includes cookies or tokens, the handler returns the DynamoDB item, and the attacker’s script reads it. Even if the endpoint enforces its own authorization, the CORS layer effectively bypasses same-origin enforcement, turning a correctly authorized DynamoDB lookup into a data leak.
Middleware-style logging or tracing that echoes request IDs or table names in headers or response bodies compounds the risk. If those values are derived from or linked to DynamoDB attributes, they may expose internal schema details cross-origin. Therefore, combining a wildcard CORS setup with any data source—especially a centralized store like DynamoDB—requires precise origin specification and careful handling of credentials to prevent unintended data exposure across origins.
Dynamodb-Specific Remediation in Gorilla Mux — concrete code fixes
Remediation centers on replacing the wildcard with an explicit origin and ensuring credentials are only allowed when necessary. In Gorilla Mux, set CORS headers in a dedicated handler or middleware so that responses include a specific origin rather than *. When credentials are not required, omit Access-Control-Allow-Credentials entirely. When credentials are required, validate the incoming Origin against an allowlist and echo it back in the header.
Below is a concise, working example of a CORS middleware for Gorilla Mux that reads from a DynamoDB table to enforce origin policies at runtime. This approach ensures that only approved origins can access responses that may include DynamoDB data, and it avoids exposing items to arbitrary web pages.
// main.go
package main
import (
"context"
"encoding/json"
"net/http"
"strings"
"github.com/gorilla/mux"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/dynamodb"
)
// OriginRecord models a row in an allowlist table.
// Table: CORSAllowlist PartitionKey: Origin (string)
type OriginRecord struct {
Origin string `json:"origin"`
}
var cfg, _ = config.LoadDefaultConfig(context.TODO())
ddb := dynamodb.NewFromConfig(cfg)
const allowlistTable = "CORSAllowlist"
// isOriginAllowed checks DynamoDB for the given origin.
func isOriginAllowed(origin string) (bool, error) {
out, err := ddb.GetItem(context.TODO(), &dynamodb.GetItemInput{
TableName: aws.String(allowlistTable),
Key: map[string]aws.AttributeValue{
"origin": &aws.StringAttributeValue{Value: origin},
},
})
if err != nil {
return false, err
}
return out.Item != nil, nil
}
// corsMiddleware adds safe CORS headers based on DynamoDB allowlist.
func corsMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
reqOrigin := r.Header.Get("Origin")
if reqOrigin == "" {
next.ServeHTTP(w, r)
return
}
allowed, err := isOriginAllowed(reqOrigin)
if err != nil || !allowed {
next.ServeHTTP(w, r)
return
}
w.Header().Set("Access-Control-Allow-Origin", reqOrigin)
w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Authorization, Content-Type")
// Only include credentials when you truly need them.
// w.Header().Set("Access-Control-Allow-Credentials", "true")
if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
return
}
next.ServeHTTP(w, r)
})
}
// getItemHandler fetches an item from DynamoDB and returns it.
func getItemHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id := vars["id"]
out, err := ddb.GetItem(context.TODO(), &dynamodb.GetItemInput{
TableName: aws.String("ItemsTable"),
Key: map[string]aws.AttributeValue{
"id": &aws.StringAttributeValue{Value: id},
},
})
if err != nil || out.Item == nil {
http.Error(w, `{"error":"not found"}`, http.StatusNotFound)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(out.Item)
}
func main() {
r := mux.NewRouter()
r.Use(corsMiddleware)
r.HandleFunc("/items/{{id}}", getItemHandler).Methods("GET")
http.ListenAndServe(":8080", r)
}
Key points specific to DynamoDB: ensure your allowlist table uses a simple schema (Origin as partition key) for fast lookups, and keep item responses minimal to reduce exposure surface. Avoid returning entire items when only a subset of attributes is needed; project only required fields at the DynamoDB level using expression attribute names if necessary. Combine this origin validation with per-endpoint authorization checks to defend against BOLA even if CORS is correctly configured.
For production, rotate credentials used by this middleware, enable AWS SDK tracing for debugging, and monitor failed origin lookups to detect scanning attempts. Using an explicit origin list stored in DynamoDB gives you an auditable, runtime-managed allowlist that adapts without redeploying your Gorilla Mux service.
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 |