Cors Wildcard in Echo Go with Dynamodb
Cors Wildcard in Echo Go with Dynamodb — how this specific combination creates or exposes the vulnerability
A CORS wildcard configuration in an Echo Go service that also interacts with DynamoDB can unintentionally expose both API and data-layer risks. When WithAllowOrigins([]string{"*"}) is set on an Echo router handling authenticated or role-based requests, browsers allow any origin to read the response. If the handler returns sensitive DynamoDB data and includes per-user or per-role information without verifying the origin, a wildcard enables any external site to make authenticated-origin requests via your frontend JavaScript. This can facilitate privilege escalation when the response contains IAM-related details or when preflighted OPTIONS requests bypass intended authorization checks.
Consider an Echo route that queries DynamoDB for user data and returns JSON without validating the Origin header:
// Echo Go handler with CORS wildcard and DynamoDB call
func GetUserData(c echo.Context) error {
sess := session.Must(session.NewSession(&aws.Config{
Region: aws.String("us-east-1")},
))
svc := dynamodb.New(sess)
input := &dynamodb.GetItemInput{
TableName: aws.String("users"),
Key: map[string]*dynamodb.AttributeValue{
"user_id": {S: aws.String(c.Param("id"))},
},
}
result, err := svc.GetItem(context.TODO(), input)
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
}
return c.JSON(result.Item)
}
If this handler is mounted under WithAllowOrigins([]string{"*"}), any site can call this endpoint and receive another user’s data when the frontend erroneously passes an ID. The wildcard removes the same-origin policy enforcement on the server side, while DynamoDB returns data based on the caller-supplied key, not the caller’s authorization context. This combination can lead to information disclosure that appears to originate from your service.
Additionally, when the response includes IAM fields (e.g., permissions, roles) or session tokens, a wildcard enables client-side exfiltration via embedded scripts. Attackers can craft URLs that trick authenticated users into triggering cross-origin requests, effectively turning your Echo API into a proxy for DynamoDB data. Even without modifying server code, the presence of a wildcard broadens the impact of client-side vulnerabilities elsewhere in your app.
Dynamodb-Specific Remediation in Echo Go — concrete code fixes
Remediation focuses on tightening CORS and ensuring DynamoDB access respects per-request authorization. Replace the wildcard with explicit origins and add per-route or global middleware that validates origins against an allowlist. Combine this with DynamoDB condition checks or caller-bound queries to avoid returning data based solely on client-supplied identifiers.
First, configure CORS with specific origins and, if needed, credentials:
// Echo Go router with restricted CORS
allowedOrigins := []string{"https://app.example.com", "https://admin.example.com"}
c := middleware.CORSWithConfig(middleware.CORSConfig{
AllowOrigins: allowedOrigins,
AllowMethods: []string{echo.GET, echo.POST, echo.OPTIONS},
AllowHeaders: []string{echo.HeaderAuthorization, echo.HeaderContentType},
ExposeHeaders: []string{"X-Total-Count"},
MaxAge: 60,
})
r.Use(c)
Second, enforce authorization inside the handler so DynamoDB queries are scoped to the authenticated subject rather than trusting the client-supplied ID:
// Echo Go handler with ownership check against DynamoDB
func GetUserDataSecure(c echo.Context) error {
userID := c.Get("user_id").(string) // from JWT or session
sess := session.Must(session.NewSession(&aws.Config{
Region: aws.String("us-east-1")},
))
svc := dynamodb.New(sess)
input := &dynamodb.GetItemInput{
TableName: aws.String("users"),
Key: map[string]*dynamodb.AttributeValue{
"user_id": {S: aws.String(userID)},
},
}
result, err := svc.GetItem(context.TODO(), input)
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
}
if result.Item == nil {
return echo.NewHTTPError(http.StatusNotFound, "user not found")
}
return c.JSON(result.Item)
}
For broader protection, use middleware that enforces row-level ownership for list or query endpoints:
// Echo Go middleware to inject subject into context for DynamoDB queries
func SubjectMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
token := c.Get("user").(*jwt.Token)
subject, _ := token.Claims["sub"].(string)
c.Set("user_id", subject)
return next(c)
}
}
// Usage
r.GET("/users/:id", SubjectMiddleware(GetUserDataSecure))
These changes remove the wildcard, bind DynamoDB access to the authenticated subject, and ensure that cross-origin requests cannot leverage your service as an unrestricted data proxy.
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 |