Memory Leak in Fastapi with Basic Auth
Memory Leak in Fastapi with Basic Auth — how this specific combination creates or exposes the vulnerability
A memory leak in a FastAPI service that uses HTTP Basic Authentication can stem from how requests and authentication state are managed across asynchronous calls. When credentials are parsed on every request without proper cleanup, large or unbounded data structures (for example, dictionaries that accumulate per-request context or cached decoded credentials) can grow over time. In an async environment, if references to request-scene objects such as the decoded username or password are unintentionally retained—such as attaching them to global caches, logging structures, or long-lived background tasks—the Python garbage collector may not reclaim them promptly. This pattern is more likely when developers couple authentication logic tightly with business logic, creating retention paths that persist beyond the request lifecycle.
Consider a naive handler that decodes credentials and stores them for later use across multiple async functions:
from fastapi import FastAPI, Depends, HTTPException, Header
import base64
app = FastAPI()
credential_store = {} # Intentionally retained across requests; risky
def get_basic_auth(auth: str = Header(None)):
if not auth or not auth.startswith('Basic '):
raise HTTPException(status_code=401, detail='Missing or invalid Authorization header')
token = auth.split(' ')[1]
decoded = base64.b64decode(token).decode('utf-8')
user, pwd = decoded.split(':', 1)
# Storing per-request data in a global structure can retain memory
credential_store[user] = {'password': pwd, 'raw': decoded}
return user
@app.get('/items')
def read_items(user: str = Depends(get_basic_auth)):
return {'user': user, 'data': 'example'}
In this scenario, credential_store accumulates entries indefinitely, holding decoded passwords and raw tokens. Even if the store is intended for short-term caching, without eviction it becomes a source of unbounded memory growth. A memory scan from middleBrick may surface this as a high-severity finding under Data Exposure or Unsafe Consumption, because retained credentials increase the attack surface and may be exposed through insecure logging or error paths. The issue is compounded when the service handles many concurrent authenticated sessions, as the accumulation rate scales with traffic.
Another contributor is improper handling of streaming bodies or large payloads where the request content is read into memory repeatedly without release, especially when authentication adds extra per-request buffers. MiddleBrick’s checks for Data Exposure and Unsafe Consumption are designed to detect such retention patterns, emphasizing that findings should be remediated by limiting object lifetimes and avoiding global accumulation of request-sc敏感数据.
Basic Auth-Specific Remediation in Fastapi — concrete code fixes
To mitigate memory leaks when using HTTP Basic Authentication in FastAPI, ensure decoded credentials are not retained globally and that per-request objects are short-lived. Use dependency injection to provide credentials within the request scope and clear any temporary structures before the response is returned. Avoid caching passwords in plain text; if caching is necessary, use bounded, time-bound stores with explicit eviction.
Here is a safer pattern that decodes credentials per request without persisting them:
from fastapi import FastAPI, Depends, HTTPException, Header, Security
import base64
app = FastAPI()
def get_basic_auth(auth: str = Header(None)):
if not auth or not auth.startswith('Basic '):
raise HTTPException(status_code=401, detail='Missing or invalid Authorization header')
try:
token = auth.split(' ')[1]
decoded = base64.b64decode(token).decode('utf-8')
user, pwd = decoded.split(':', 1)
# Return only what is needed; avoid storing raw credentials
return {'user': user, 'password': pwd}
except (IndexError, UnicodeDecodeError, ValueError):
raise HTTPException(status_code=401, detail='Invalid authorization token')
@app.get('/items')
def read_items(credentials: dict = Security(get_basic_auth)):
# Use credentials within the request scope; no global retention
return {'user': credentials['user'], 'data': 'example'}
This approach confines decoded data to the request lifetime and does not attach it to module-level structures. For applications that require credential validation against a backend, perform the check inside the dependency and avoid caching the password. If you must cache tokens or derived values, use a fixed-size structure (for example, an OrderedDict with maxlen) or a time-based eviction mechanism to bound memory growth.
Additionally, ensure that any logging or error handling does not inadvertently include the password or raw authorization header. FastAPI’s default exception handlers should be reviewed so that stack traces do not expose sensitive data, which would be flagged by middleBrick’s Data Exposure checks. By combining scoped dependencies, bounded caches, and careful handling of decoded values, you can reduce the risk of memory leaks while maintaining Basic Authentication in FastAPI.