HIGH cors wildcardfastapidynamodb

Cors Wildcard in Fastapi with Dynamodb

Cors Wildcard in Fastapi with Dynamodb — how this specific combination creates or exposes the vulnerability

A CORS wildcard (Access-Control-Allow-Origin: *) in a FastAPI service that also interacts with DynamoDB can unintentionally expose sensitive data and amplify authorization flaws such as BOLA/IDOR. When allow_origins=["*"] is set together with credentials or custom headers, browsers may send authenticated requests on behalf of a user. If the FastAPI endpoint uses the caller’s identity (e.g., a Cognito-derived subject or API key) to query DynamoDB using a direct key like user_id = event["requestContext"]["authorizer"]["claims"]["sub"], the wildcard does not block the request server-side, but it widens the attack surface by allowing any origin to trigger those authenticated calls. An attacker-controlled site can invoke the endpoint via JavaScript, potentially leaking DynamoDB data that would otherwise be protected by authentication and scoped IAM policies. Because DynamoDB enforces IAM permissions per request, the service must ensure the identity it uses to sign requests is not derived from an untrusted origin; otherwise the wildcard circumvents intended origin-based controls.

Consider a typical pattern where FastAPI uses an HTTP event with a Cognito authorizer:

import json
def lambda_handler(event, context):
    user_id = event["requestContext"]["authorizer"]["claims"]["sub"]
    # Build DynamoDB client and query using user_id as partition key
    dynamodb = boto3.resource("dynamodb")
    table = dynamodb.Table("UserProfiles")
    response = table.get_item(Key={"user_id": user_id})
    return {"statusCode": 200, "body": json.dumps(response.get("Item", {}))}

If FastAPI’s CORS configuration sets allow_origins=["*"] and the response includes credentials, a malicious page can make authenticated requests to this Lambda-backed endpoint. The DynamoDB query still executes with the authorizer’s subject, but the browser’s cross-origin request may expose the data to the attacker. This combination does not change DynamoDB’s permissions, yet it enables a broader cross-origin attack chain, especially when combined with misconfigured authorization or overly permissive IAM roles. The risk is not a DynamoDB misconfiguration per se, but rather how an unrestricted CORS policy interacts with authenticated data access patterns that rely on identity claims passed from the API layer to the database layer.

Dynamodb-Specific Remediation in Fastapi — concrete code fixes

Remediation centers on tightening CORS and ensuring DynamoDB access is bound to the authenticated subject without relying on the origin. In FastAPI, avoid the wildcard and instead specify origins explicitly or use a controlled allowlist. Combine this with validating the authenticated identity before constructing the DynamoDB request. Below are two concrete approaches, including a secure FastAPI route with a DynamoDB resource using boto3.

Approach 1: Restricted CORS with explicit origins

from fastapi import FastAPI, Request, Depends, HTTPException
from fastapi.middleware.cors import CORSMiddleware
import boto3
import json

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://trusted.example.com"],
    allow_credentials=True,
    allow_methods=["GET"],
    allow_headers=["Authorization", "Content-Type"],
)

def get_db():
    return boto3.resource("dynamodb")

@app.get("/profiles/{user_id}")
def read_profile(
    user_id: str,
    request: Request,
    db = Depends(get_db)
):
    # Derive subject from a validated auth dependency in production
    subject = request.state.subject  # set by an auth dependency
    if not subject:
        raise HTTPException(status_code=401, detail="Unauthorized")
    table = db.Table("UserProfiles")
    response = table.get_item(Key={"user_id": subject})
    item = response.get("Item")
    if not item or item.get("user_id") != subject:
        raise HTTPException(status_code=403, detail="Forbidden")
    return item

Approach 2: Lambda with controlled identity mapping

When using AWS Lambda behind API Gateway with Cognito authorizers, map the claim to the DynamoDB key explicitly and avoid any permissive CORS settings in the Lambda response headers. FastAPI can be served behind a Lambda adapter (e.g., Mangum) with strict CORS handled at the API Gateway level.

import json
import boto3
def lambda_handler(event, context):
    # Validate authorizer and extract subject
    if "requestContext" not in event or "authorizer" not in event["requestContext"]:
        return {"statusCode": 401, "body": json.dumps({"error": "Unauthorized"})}
    claims = event["requestContext"]["authorizer"].get("claims", {})
    subject = claims.get("sub")
    if not subject:
        return {"statusCode": 401, "body": json.dumps({"error": "Unauthorized"})}
    # Enforce ownership at DynamoDB level using subject as partition key
    dynamodb = boto3.resource("dynamodb")
    table = dynamodb.Table("UserProfiles")
    response = table.get_item(Key={"user_id": subject})
    item = response.get("Item", {})
    # Double-check that the item belongs to the subject
    if item.get("user_id") != subject:
        return {"statusCode": 403, "body": json.dumps({"error": "Forbidden"})}
    return {"statusCode": 200, "body": json.dumps(item)}

These examples emphasize that the identity used for DynamoDB access must be validated independently of CORS. Do not rely on the origin header for authorization; instead bind the DynamoDB key directly to the authenticated subject and enforce ownership checks in your code. This approach mitigates risks even if CORS policy changes, and aligns with checks run by scanners that test for CORS misconfigurations alongside DynamoDB access patterns.

Related CWEs: dataExposure

CWE IDNameSeverity
CWE-200Exposure of Sensitive Information HIGH
CWE-209Error Information Disclosure MEDIUM
CWE-213Exposure of Sensitive Information Due to Incompatible Policies HIGH
CWE-215Insertion of Sensitive Information Into Debugging Code MEDIUM
CWE-312Cleartext Storage of Sensitive Information HIGH
CWE-359Exposure of Private Personal Information (PII) HIGH
CWE-522Insufficiently Protected Credentials CRITICAL
CWE-532Insertion of Sensitive Information into Log File MEDIUM
CWE-538Insertion of Sensitive Information into Externally-Accessible File HIGH
CWE-540Inclusion of Sensitive Information in Source Code HIGH

Frequently Asked Questions

Why is a CORS wildcard risky when DynamoDB is involved?
A wildcard allows any origin to make authenticated requests; if FastAPI uses the request’s identity to query DynamoDB, an attacker on a malicious site can trigger data exposure via cross-origin calls, even though DynamoDB permissions remain unchanged.
Does middleBrick detect CORS wildcard issues with DynamoDB integrations?
Yes, middleBrick’s 12 security checks include CORS misconfiguration analysis and can flag a wildcard in FastAPI endpoints that access DynamoDB, providing prioritized findings and remediation guidance.