HIGH api key exposurefastapi

Api Key Exposure in Fastapi

How Api Key Exposure Manifests in Fastapi

Api Key Exposure in Fastapi applications typically occurs through several Fastapi-specific patterns. The most common vulnerability appears when developers implement custom authentication middleware that inadvertently logs or exposes API keys in error responses. For example, a naive implementation might catch exceptions and return the raw API key in the response body:

@app.exception_handler(APIException)
async def api_exception_handler(request: Request, exc: APIException):
    return JSONResponse(
        status_code=exc.status_code,
        content={"detail": f"Invalid API key: {exc.api_key}", "key": exc.api_key}
    )

This pattern directly exposes the API key to any client making an invalid request, violating confidentiality principles.

Another Fastapi-specific manifestation occurs with dependency injection. Developers often create API key dependencies that are too permissive:

async def get_api_key(
    x_api_key: str = Header(...),
    deprecated_api_key: str = Header(None)
):
    # Accepts both modern and deprecated keys without validation
    return x_api_key or deprecated_api_key

@app.get("/sensitive-data")
async def read_data(api_key: str = Depends(get_api_key)):
    # No actual validation performed
    return sensitive_data

This creates a situation where any header value is accepted, effectively disabling authentication.

Fastapi's automatic OpenAPI documentation generation can also expose API keys. When API key parameters are defined in path operations without proper security schemes, they appear in the generated OpenAPI spec:

@app.get("/users/me")
async def read_user_me():
    return {"username": "dummy"}

# Missing security scheme definition

Without proper security scheme configuration, API keys become visible in the interactive API documentation, allowing anyone with access to the docs to discover valid endpoints and authentication requirements.

Rate limiting implementations in Fastapi can also lead to key exposure. A common anti-pattern involves logging API keys for debugging:

@app.middleware("http")
async def api_key_logging_middleware(request: Request, call_next):
    api_key = request.headers.get("x-api-key")
    logger.info(f"API key {api_key} accessed endpoint {request.url.path}")
    response = await call_next(request)
    return response

This logs API keys in plaintext, creating a security audit trail that contains sensitive credentials.

Fastapi-Specific Detection

Detecting API key exposure in Fastapi requires examining both code patterns and runtime behavior. Static analysis should look for these specific Fastapi patterns:

Header-based authentication without validation:

# Vulnerable pattern - accepts any header value
async def get_api_key(x_api_key: str = Header(...)):
    return x_api_key

# Secure pattern - validates against known keys
async def get_api_key(x_api_key: str = Header(...)):
    if x_api_key not in VALID_API_KEYS:
        raise HTTPException(status_code=401, detail="Invalid API key")
    return x_api_key

Exception handlers that expose credentials:

# Vulnerable - returns raw API key in response
@app.exception_handler(APIException)
async def handler(request, exc):
    return JSONResponse(content={"key": exc.api_key})

# Secure - generic error message only
@app.exception_handler(APIException)
async def handler(request, exc):
    return JSONResponse(status_code=401, content={"detail": "Unauthorized"})

Logging sensitive data:

# Vulnerable - logs API keys
logger.info(f"User {api_key} accessed {endpoint}")

# Secure - logs only user IDs after authentication
logger.info(f"User {user_id} accessed {endpoint}")

Runtime detection with middleBrick specifically targets Fastapi applications by scanning the unauthenticated attack surface. The scanner identifies API key exposure through:

  • Header analysis: Testing for predictable API key header names (x-api-key, authorization, api-key) and attempting authentication bypass
  • Response analysis: Checking for API keys in error responses, headers, or response bodies
  • Documentation analysis: Examining OpenAPI specs for exposed authentication schemes
  • Rate limiting bypass: Testing whether rate limiting is properly keyed to authenticated users

middleBrick's Fastapi-specific detection includes active probing for common Fastapi authentication patterns and validation of proper error handling. The scanner tests whether invalid API keys produce generic error messages or leak information about valid keys.

Command-line scanning with middleBrick:

middlebrick scan https://api.example.com --fastapi --output json

This command enables Fastapi-specific security checks and outputs findings in JSON format for integration with other tools.

Fastapi-Specific Remediation

Remediating API key exposure in Fastapi requires implementing secure authentication patterns using Fastapi's built-in features. The most secure approach uses Fastapi's dependency injection system with proper validation:

Secure API key dependency:

from fastapi import HTTPException, Depends, status
from typing import Optional
from jose import jwt

# Store API keys securely (never in code)
API_KEYS_DB = {
    "valid-key-123": {"user_id": 1, "permissions": ["read"]},
    "admin-key-abc": {"user_id": 2, "permissions": ["read", "write"]}
}

def get_api_key(
    x_api_key: str = Header(...),
    deprecated_api_key: Optional[str] = Header(None)
):
    """Secure API key validation with deprecation support"""
    key = x_api_key or deprecated_api_key
    
    if key not in API_KEYS_DB:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid API key",
            headers={"WWW-Authenticate": "Bearer"}
        )
    
    return API_KEYS_DB[key]

async def get_current_user(api_key_data: dict = Depends(get_api_key)):
    """Return authenticated user information"""
    return api_key_data

Secure exception handling:

@app.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException):
    """Generic error response without sensitive data"""
    return JSONResponse(
        status_code=exc.status_code,
        content={"detail": "Authentication failed" if exc.status_code == 401 else exc.detail}
    )

Rate limiting with API key awareness:

from fastapi import Request
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address
from slowapi.errors import RateLimitExceeded

limiter = Limiter(key_func=get_remote_address)
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)

async def api_key_rate_limit(request: Request, call_next):
    api_key = request.headers.get("x-api-key")
    if api_key:
        # Rate limit per API key
        key = f"apikey:{api_key}"
    else:
        # Rate limit by IP for unauthenticated requests
        key = get_remote_address(request)
    
    if not limiter.is_allowed(key, 100, 3600):
        raise RateLimitExceeded()
    
    return await call_next(request)

Secure logging practices:

import logging
from uuid import uuid4

logger = logging.getLogger(__name__)

def get_api_key(request: Request):
    api_key = request.headers.get("x-api-key")
    if api_key:
        # Log only key hash for correlation
        key_hash = hash(api_key)
        logger.info(f"Authenticated request from key hash {key_hash}")
    return api_key

OpenAPI security scheme configuration:

from fastapi import FastAPI, Security
from fastapi.security.api_key import APIKeyHeader

api_key_scheme = APIKeyHeader(name="x-api-key", scheme_name="API Key")

@app.get("/secure-endpoint", security=[api_key_scheme])
async def secure_endpoint(
    api_key: str = Security(api_key_scheme)
):
    return {"message": "Authenticated"}

This configuration ensures API keys are properly documented in OpenAPI specs without exposing them in the interactive documentation. middleBrick can verify that these security schemes are correctly implemented and that no API keys are exposed through documentation.

Frequently Asked Questions

How can I test my Fastapi application for API key exposure?
Use middleBrick's self-service scanner by running 'middlebrick scan https://your-api.com'. The scanner tests for common Fastapi authentication patterns, checks if API keys appear in error responses or documentation, and verifies that rate limiting is properly implemented. The scan takes 5-15 seconds and provides a security score with specific findings about API key exposure vulnerabilities.
What's the difference between API key exposure and other authentication issues in Fastapi?
API key exposure specifically involves credentials being visible to unauthorized parties, either through error responses, logging, or documentation. Other authentication issues like missing authentication or weak validation are different problems. middleBrick's API key exposure detection focuses on whether valid API keys could be discovered or intercepted by attackers, while other checks handle authentication bypass and privilege escalation separately.