Cors Wildcard in Fastapi with Hmac Signatures
Cors Wildcard in Fastapi with Hmac Signatures — how this specific combination creates or exposes the vulnerability
Cross-origin resource sharing (CORS) misconfigurations are a common web security risk, and combining a wildcard CORS policy with HMAC-based request authentication in FastAPI can unintentionally expose sensitive endpoints. A CORS wildcard allows any origin to make browser-based requests, which is acceptable for public read-only data but dangerous when requests require cryptographic proof of integrity and origin-bound authorization.
Consider a FastAPI service that uses HMAC signatures to authenticate and ensure the integrity of requests. The server generates a signature on the client side using a shared secret and sends it in a header (e.g., X-API-Signature). The server then verifies this signature before processing the request. If the CORS configuration sets Access-Control-Allow-Origin: * and exposes headers like the signature or related tokens to any requesting origin, a browser-based attacker can make authenticated requests on behalf of other users. Because the browser automatically includes credentials like cookies or custom headers in cross-origin requests when credentials mode is not strict, the attacker can leverage the wildcard to observe or relay signed requests.
This combination also interacts poorly with preflight requests. Browsers issue an OPTIONS request to check CORS permissions before the actual request. If the FastAPI application does not strictly validate the Origin and does not restrict allowed methods and headers, the preflight may succeed for any site. Even if the application validates the HMAC on the endpoint, a wildcard CORS policy can allow an attacker’s page to initiate requests and use techniques like timing attacks or repeated probing to infer validation behavior or leak information through error messages or response timings.
In practice, this issue maps to the BFLA/Privilege Escalation and Authentication checks performed by middleBrick, which tests unauthenticated attack surfaces including CORS behavior and signature validation logic. The scanner can detect whether a wildcard CORS origin is present alongside endpoints that rely on HMAC signatures, highlighting the risk that any origin may trigger authenticated actions.
Hmac Signatures-Specific Remediation in Fastapi — concrete code fixes
To secure a FastAPI application using HMAC signatures, you must tightly couple signature validation with strict CORS policies. Never pair a permissive CORS wildcard with endpoints that rely on cryptographic signatures for integrity and authentication. Instead, explicitly allow only trusted origins, and ensure that signature verification occurs before any business logic is executed.
Below is a complete, syntactically correct example of a FastAPI application that uses HMAC signatures for request integrity and applies strict CORS rules. The server generates a signature for a payload and verifies it on each request. The CORS middleware is configured with specific origins, and the signature header is not exposed to untrusted origins.
from fastapi import FastAPI, Depends, Header, HTTPException, Request
from fastapi.middleware.cors import CORSMiddleware
import hmac
import hashlib
import time
import os
import base64
app = FastAPI()
# Strict CORS configuration: only allow known origins
app.add_middleware(
CORSMiddleware,
allow_origins=["https://trusted.example.com", "https://app.example.com"],
allow_credentials=True,
allow_methods=["POST", "GET", "OPTIONS"],
allow_headers=["X-API-Key", "X-API-Signature", "Content-Type"],
expose_headers=["X-API-Request-Id"],
)
SHARED_SECRET = os.environ.get("HMAC_SHARED_SECRET", "dev-secret-change-in-prod")
def verify_hmac_signature(payload: bytes, signature_header: str) -> bool:
"""Verify that the signature matches the payload using HMAC-SHA256."""
computed = hmac.new(
SHARED_SECRET.encode("utf-8"),
payload,
hashlib.sha256,
).digest()
computed_b64 = base64.b64encode(computed).decode("utf-8")
return hmac.compare_digest(computed_b64, signature_header)
def validate_request(request: Request, x_api_key: str = Header(...), x_api_signature: str = Header(...)):
"""Dependency that validates HMAC signature and required headers."""
if x_api_key != "expected-public-key": # Example API key check; use a robust auth scheme in production
raise HTTPException(status_code=401, detail="Invalid API key")
body = request.body()
if not body:
raise HTTPException(status_code=400, detail="Empty body")
if not verify_hmac_signature(body, x_api_signature):
raise HTTPException(status_code=403, detail="Invalid signature")
return True
@app.post("/secure-action")
async def secure_action(request: Request, _: bool = Depends(validate_request)):
"""An endpoint that requires a valid HMAC signature and a trusted origin."""
return {"status": "ok", "message": "Action executed securely"}
@app.get("/public-data")
async def public_data(request: Request):
"""A public endpoint with no HMAC requirement but still restricted by CORS."""
return {"data": "public"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
Key remediation points:
- Use
allow_originswith explicit trusted domains instead of["*"]. Do not expose signature-bearing responses to arbitrary origins. - Validate the HMAC on the server side using
hmac.compare_digestto prevent timing attacks. - Do not include secrets or sensitive tokens in response headers when serving wildcard origins.
- Ensure preflight requests are handled consistently; do not skip signature validation for OPTIONS or preflight responses.
By combining strict origin policies with robust HMAC verification, you mitigate the risk that a wildcard CORS policy undermines your cryptographic protections. middleBrick’s scans can highlight mismatches between CORS configuration and authentication mechanisms, helping you identify and tighten overly permissive rules before they are abused.
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 |