Security Misconfiguration in Fastapi with Api Keys
Security Misconfiguration in Fastapi with Api Keys — how this specific combination creates or exposes the vulnerability
Security misconfiguration in FastAPI applications that use API keys often arises from how keys are defined, validated, and scoped. When keys are expected in specific locations (e.g., headers) but the application fails to enforce strict validation, paths with incomplete protections become entry points for unauthorized access.
A common pattern involves declaring an API key scheme but omitting required enforcement on certain routes. For example, using Security dependencies on some endpoints while leaving others without any dependency creates an inconsistency that effectively exposes unprotected paths. Additionally, failing to require the key prefix (e.g., Bearer vs raw key) can allow malformed inputs to pass through if validation logic is permissive.
Misconfiguration also occurs when scopes or roles are declared but not properly enforced. An endpoint might list required scopes in the OpenAPI spec but the dependency implementation skips scope checks, enabling privilege issues across authenticated contexts. Another frequent error is leaking key validation logic into client-side code or logs, which can expose key formats or presence through application output.
Runtime findings frequently reveal these gaps through unauthenticated or insufficiently authenticated probes. Because middleBrick runs 12 security checks in parallel, it flags routes where API key dependencies are missing or inconsistently applied, and cross-references these findings with the OpenAPI/Swagger spec (including $ref resolution) to ensure declared protections match runtime behavior.
For LLM-related security, API keys embedded in prompts or model configurations risk system prompt leakage or unauthorized usage patterns. middleBrick’s LLM/AI Security checks specifically test for exposed key formats in outputs and validate that endpoints requiring keys are not bypassed through prompt injection or jailbreak techniques.
Api Keys-Specific Remediation in Fastapi — concrete code fixes
To remediate API key misconfiguration in FastAPI, consistently apply security dependencies to all routes that require protection, enforce strict key formats, and align runtime behavior with your OpenAPI declarations. Below are concrete examples demonstrating secure patterns.
1. Consistent API key dependency across all routes
Ensure every route that needs protection uses the same API key dependency. Avoid mixing protected and unprotected routes without explicit intent.
from fastapi import FastAPI, Depends, Security, HTTPException, status
from fastapi.security import APIKeyHeader
app = FastAPI()
api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False)
def get_api_key(api_key: str = Security(api_key_header)):
if api_key != "my-secret-key":
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Invalid or missing API key"
)
return api_key
@app.get("/public")
def public_endpoint():
return {"message": "public"}
@app.get("/secure")
def secure_endpoint(api_key: str = Security(get_api_key)):
return {"message": "secure", "api_key_present": bool(api_key)}
2. Enforce key prefix and strict validation
Validate that keys include a required scheme (e.g., Bearer) and reject malformed values early.
from fastapi import FastAPI, Security, HTTPException, status
from fastapi.security import APIKeyHeader
app = FastAPI()
api_key_header = APIKeyHeader(name="Authorization", auto_error=False)
def verify_api_key(authorization: str = Security(api_key_header)):
if authorization is None:
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Authorization header missing")
if not authorization.startswith("Bearer "):
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid authorization format")
token = authorization[len("Bearer "):]
if token != "my-secret-key":
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Invalid token")
return token
@app.get("/items")
def read_items(token: str = Security(verify_api_key)):
return {"items": ["a", "b"]}
3. Use scopes and enforce them in dependencies
Define and validate scopes to control access per endpoint, ensuring declared scopes are checked at runtime.
from fastapi import FastAPI, Security, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
app = FastAPI()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
class Scopes:
items_read = "items:read"
items_write = "items:write"
def get_current_user(token: str = Security(oauth2_scheme)):
# simplified; validate token and extract scopes
return {"user": "alice", "scopes": [Scopes.items_read]}
def require_scope(required_scope: str):
def scope_dependency(user: dict = Security(get_current_user)):
if required_scope not in user.get("scopes", []):
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Insufficient scope")
return user
return scope_dependency
@app.get("/items")
def list_items(user: dict = Security(require_scope(Scopes.items_read))):
return {"items": ["hammer", "nails"]}
@app.post("/items")
def create_item(user: dict = Security(require_scope(Scopes.items_write))):
return {"status": "created"}
4. Align OpenAPI spec with runtime enforcement
Declare security schemes and requirements in your OpenAPI spec and ensure runtime dependencies reflect them. Use $ref consistently so spec definitions and implementation stay in sync.
openapi: 3.0.3
info:
title: Secure API
version: 1.0.0
paths:
/secure:
get:
summary: Requires API key
security:
- ApiKeyAuth: []
responses:
'200':
description: OK
components:
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: X-API-Key
5. Avoid key leakage in logs and outputs
Ensure keys are not echoed in responses or logs. When returning diagnostic information, redact or omit the key value.
import logging
logger = logging.getLogger(__name__)
@app.get("/debug")
def debug_key(api_key: str = Security(get_api_key)):
# Safe: log only presence, not the key value
logger.info("API key received: %s", bool(api_key))
return {"ok": True}