HIGH cors wildcardfastapi

Cors Wildcard in Fastapi

How Cors Wildcard Manifests in Fastapi

CORS wildcard configuration in FastAPI can create serious security vulnerabilities when developers use overly permissive settings. The most common manifestation occurs when developers set origins="*" in their CORS middleware, allowing any domain to make cross-origin requests to their API.

Consider this vulnerable FastAPI code:

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

This configuration allows any website to make authenticated requests to your FastAPI backend. The critical issue is the combination of allow_origins="*" with allow_credentials=True. According to the CORS specification, browsers will reject this combination, but some FastAPI versions and browsers may handle it inconsistently.

Attackers can exploit this by hosting malicious websites that make authenticated requests to your FastAPI endpoints. If users visit the malicious site while logged into your FastAPI application, the attacker can:

  • Steal session cookies or JWT tokens
  • Make API calls on behalf of authenticated users
  • Extract sensitive data through timing attacks
  • Trigger actions like money transfers or data deletion

Another FastAPI-specific manifestation occurs with improper dependency injection. Consider:

@app.post("/sensitive-data")
async def get_data(
    db: Database = Depends(get_db),  # Database injected from any origin
    user: User = Depends(get_current_user)
):
    return db.query_user_data(user.id)

When CORS is misconfigured, the Database dependency can be accessed from any origin, exposing your data layer to cross-origin attacks.

Fastapi-Specific Detection

Detecting CORS wildcard vulnerabilities in FastAPI requires both static analysis and runtime scanning. Here's how to identify these issues:

Static Code Analysis:

import ast

def find_cors_wildcard_issues(file_path):
    with open(file_path, 'r') as f:
        tree = ast.parse(f.read())
    
    issues = []
    for node in ast.walk(tree):
        if isinstance(node, ast.Call):
            if isinstance(node.func, ast.Attribute):
                if node.func.attr == 'add_middleware':
                    for keyword in node.keywords:
                        if keyword.arg == 'allow_origins':
                            if isinstance(keyword.value, ast.List):
                                for element in keyword.value.elts:
                                    if isinstance(element, ast.Constant) and element.value == '*':
                                        issues.append({
                                            'line': node.lineno,
                                            'message': 'CORS wildcard detected'
                                        })
    return issues

Runtime Testing with middleBrick: middleBrick's black-box scanning can detect CORS misconfigurations without requiring source code access. The scanner tests:

  • Whether credentials are accepted from arbitrary origins
  • HTTP method restrictions
  • Header filtering effectiveness
  • Preflight request handling

Manual Testing:

# Test with curl
curl -H "Origin: http://evil.com" \
     -H "Access-Control-Request-Method: POST" \
     -H "Access-Control-Request-Headers: X-Requested-With" \
     --verbose \
     https://your-fastapi-app.com

# Check response headers for:
# - Access-Control-Allow-Origin: *
# - Access-Control-Allow-Credentials: true

middleBrick CLI Integration:

# Scan your FastAPI endpoint
middlebrick scan https://api.yourdomain.com --output json

# Check for CORS-related findings in the report
# middleBrick will flag wildcard origins, missing method restrictions, and credential issues

Fastapi-Specific Remediation

Fixing CORS wildcard vulnerabilities in FastAPI requires a security-first approach. Here are specific remediation strategies:

1. Whitelist Specific Origins:

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

# Define allowed origins explicitly
ALLOWED_ORIGINS = [
    "https://yourdomain.com",
    "https://app.yourdomain.com",
    "https://admin.yourdomain.com",
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=ALLOWED_ORIGINS,
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
    allow_headers=["Authorization", "Content-Type", "X-Requested-With"],
)

2. Dynamic Origin Validation:

class DynamicCORSMiddleware(CORSMiddleware):
    def __init__(self, app, allow_origins=None, **kwargs):
        super().__init__(app, allow_origins, **kwargs)
        self.allowed_origins = set(allow_origins or [])
    
    async def __call__(self, request: Request, call_next):
        origin = request.headers.get("origin")
        if origin and origin in self.allowed_origins:
            request.state.cors_origin = origin
        return await super().__call__(request, call_next)

# Usage
app.add_middleware(
    DynamicCORSMiddleware,
    allow_origins=["https://yourdomain.com"],
    allow_credentials=True,
)

3. Environment-Based Configuration:

import os
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

# Load from environment with default
ALLOWED_ORIGINS = os.getenv(
    "CORS_ALLOWED_ORIGINS",
    "https://yourdomain.com,https://app.yourdomain.com"
).split(",")

app.add_middleware(
    CORSMiddleware,
    allow_origins=ALLOWED_ORIGINS,
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
    allow_headers=["Authorization", "Content-Type", "X-Requested-With"],
)

4. Security Headers Integration:

from fastapi import FastAPI
from starlette.middleware.cors import CORSMiddleware
from starlette.middleware import Middleware

class SecurityMiddleware:
    async def __call__(self, request: Request, call_next):
        response = await call_next(request)
        response.headers["X-Frame-Options"] = "DENY"
        response.headers["X-Content-Type-Options"] = "nosniff"
        response.headers["X-XSS-Protection"] = "1; mode=block"
        return response

app = FastAPI(
    middleware=[
        Middleware(CORSMiddleware, allow_origins=["https://yourdomain.com"]),
        Middleware(SecurityMiddleware),
    ]
)

5. Testing Your Fix:

import httpx

def test_cors_configuration():
    origins = ["https://yourdomain.com", "https://evil.com"]
    
    for origin in origins:
        response = httpx.options(
            "https://api.yourdomain.com/endpoint",
            headers={
                "Origin": origin,
                "Access-Control-Request-Method": "POST",
                "Access-Control-Request-Headers": "X-Requested-With"
            }
        )
        
        if origin == "https://yourdomain.com":
            assert response.status_code == 200
            assert response.headers["access-control-allow-origin"] == origin
        else:
            assert response.status_code == 403

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 using allow_origins="*" with allow_credentials=True dangerous in FastAPI?
This combination violates the CORS specification and can lead to inconsistent behavior across browsers and FastAPI versions. It allows any website to make authenticated requests to your API, potentially exposing user data and enabling account takeover attacks.
How can I test my FastAPI CORS configuration for vulnerabilities?
Use middleBrick's CLI tool to scan your API endpoint: 'middlebrick scan https://api.yourdomain.com'. middleBrick tests for wildcard origins, missing method restrictions, and credential issues. You can also manually test with curl by sending OPTIONS requests from different origins.