Cors Wildcard in Fastapi with Jwt Tokens
Cors Wildcard in Fastapi with Jwt Tokens — how this specific combination creates or exposes the vulnerability
In FastAPI, configuring CORS with a wildcard origin (origins=["*"]) while also protecting endpoints with JWT tokens can unintentionally expose authentication and authorization mechanisms. When allow_credentials is set to True alongside a wildcard origin, browsers are prevented from sending cookies or authorization headers cross-origin, but more critically, the combination can weaken the effective enforcement of token-based protections in certain client-side scenarios.
Consider a FastAPI application that validates JWT access tokens in a dependency and applies a global CORS policy with origins=["*"]. An attacker-controlled website can initiate authenticated requests from a victim’s browser if the application relies on cookies for session-like token storage. Because the wildcard origin does not restrict which frontend can make requests, and if the client mistakenly includes the JWT in an Authorization header from a compromised origin, the endpoint may still process the token without origin validation. This can facilitate cross-origin token leakage in browser contexts where the client reads responses, enabling token exfiltration via reflected or stored XSS combined with CORS misconfiguration.
Moreover, some Single Page Applications (SPAs) use the Authorization: Bearer <token> pattern and assume CORS protections are sufficient. With a wildcard origin and permissive CORS methods and headers, malicious origins can craft preflighted requests that include credentials-like headers. While the server does not allow credentials with origins=["*"], developers sometimes relax rules in production by setting allow_credentials=True to work around legacy clients, inadvertently permitting credentialed cross-origin requests that bypass intended same-origin token usage policies.
In the context of the LLM/AI Security checks provided by middleBrick, such a configuration is flagged because it can enable token exposure across origins and complicate traceability of token usage. middleBrick scans unauthenticated attack surfaces and tests input validation and data exposure, identifying origins that accept untrusted cross-origin requests even when JWT validation is present. By correlating OpenAPI specs with runtime behavior, the scanner detects whether CORS rules inadvertently weaken token-based access controls, which could lead to tokens being read by unauthorized origins in certain browser-based attack chains.
Real-world attack patterns include exploiting misconfigured CORS with reflected XSS to steal JWTs, or leveraging wildcard origins to perform cross-origin AJAX requests that reveal whether token validation behaves differently per origin. These behaviors are relevant to frameworks like FastAPI where developers must explicitly define allowed origins rather than relying on defaults. The presence of JWT tokens does not inherently prevent cross-origin misuse if CORS is too permissive.
Jwt Tokens-Specific Remediation in Fastapi — concrete code fixes
To secure FastAPI applications using JWT tokens, CORS must be configured with explicit origins and strict credential handling. Avoid wildcard origins when JWT validation is enforced, and only allow credentials for known origins. The following patterns demonstrate secure configurations.
Secure CORS with JWT Bearer tokens
Define a CORS policy that enumerates allowed origins and disables credentials unless necessary. Validate the Origin header manually if you require dynamic origin checks.
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.middleware.cors import CORSMiddleware
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
import jwt
from typing import List
app = FastAPI()
security = HTTPBearer()
# Explicitly list allowed origins
origins = [
"https://app.example.com",
"https://admin.example.com",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=False, # Disable when using bearer tokens in headers
allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
allow_headers=["Content-Type", "Authorization"],
)
def decode_token(token: str) -> dict:
# Replace with your secret and algorithm
try:
payload = jwt.decode(token, "YOUR_SECRET_KEY", algorithms=["HS256"])
return payload
except jwt.ExpiredSignatureError:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Token expired",
headers={"WWW-Authenticate": "Bearer"},
)
except jwt.InvalidTokenError:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid token",
headers={"WWW-Authenticate": "Bearer"},
)
def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(security)) -> dict:
token = credentials.credentials
payload = decode_token(token)
# Add authorization logic, e.g., role checks
return payload
@app.get("/secure-data")
def read_secure_data(user: dict = Depends(get_current_user)):
return {"data": "protected", "user": user}
Dynamic origin validation (optional)
If you must support dynamic origins, implement an endpoint that validates the Origin header against a denylist/allowlist and set CORS per request using request.headers. Do not enable allow_credentials=True with a wildcard origin.
from fastapi import Request
from fastapi.middleware.cors import CORSMiddleware
# Example of dynamic CORS setup (simplified)
def get_cors_config(request: Request):
allowed = {"https://app.example.com", "https://admin.example.com"}
origin = request.headers.get("origin")
if origin in allowed:
return CORSMiddleware(
allow_origins=[origin],
allow_credentials=False,
allow_methods=["GET", "POST"],
allow_headers=["Authorization", "Content-Type"],
)
return None # or default safe config
Recommendations
- Never set
origins=["*"]together withallow_credentials=True. - Use
HTTPBeareror custom dependencies to validate JWTs and avoid storing tokens in cookies unless necessary. - Ensure token validation includes issuer, audience, and expiration checks.
- Leverage middleBrick’s scans to detect CORS misconfigurations and token exposure risks; its findings map to OWASP API Top 10 and can guide remediation.
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 |