Header Injection in Fastapi
How Header Injection Manifests in Fastapi
Header injection vulnerabilities in Fastapi applications occur when user-controlled data flows into HTTP response headers without proper validation or encoding. Fastapi's asynchronous nature and dependency injection system create unique attack vectors that developers must understand.
The most common Fastapi header injection pattern involves response headers constructed from request parameters or path variables. Consider this vulnerable Fastapi endpoint:
from fastapi import FastAPI, Request
app = FastAPI()
@app.get("/api/user/{user_id}")
async def get_user(request: Request, user_id: str):
# Vulnerable: user_id flows directly into response header
response = JSONResponse(
content={"message": "User data"},
headers={"X-User-ID": user_id}
)
return responseAn attacker can exploit this by requesting /api/user/123%0D%0AX-Injected: malicious. The %0D%0A sequence represents CRLF (carriage return + line feed), which breaks out of the header value and injects new headers. Fastapi's underlying Starlette framework passes these characters through to the response, creating the vulnerability.
Another Fastapi-specific pattern involves dependency injection with header manipulation:
from fastapi import Depends
def get_user_agent(request: Request) -> str:
return request.headers.get("user-agent", "unknown")
@app.get("/api/data")
async def get_data(user_agent: str = Depends(get_user_agent)):
# Vulnerable: user-agent flows into response header
return JSONResponse(
content={"data": "sensitive"},
headers={"X-User-Agent": user_agent}
)Fastapi's dependency injection system makes this pattern common, but it creates the same header injection risk when user-controlled headers flow back into responses.
Path parameter manipulation in Fastapi route definitions can also lead to header injection:
@app.get("/api/{path_param}/data")
async def get_data(path_param: str):
# Vulnerable: path_param flows into response header
return JSONResponse(
content={"data": "sensitive"},
headers={"X-Path-Param": path_param}
)Fastapi's automatic type conversion and validation don't sanitize header values, making this a persistent risk in production applications.
Fastapi-Specific Detection
Detecting header injection in Fastapi applications requires both static analysis and runtime scanning. middleBrick's Fastapi-specific scanner identifies these vulnerabilities through black-box testing of your API endpoints.
middleBrick automatically tests for header injection by sending requests with CRLF sequences in path parameters, query parameters, and headers. The scanner specifically targets Fastapi's response construction patterns, testing endpoints that:
- Return JSON responses with custom headers
- Use dependency injection for header values
- Construct response headers from request data
- Include user-controlled data in CORS headers
- Generate location headers from path parameters
The scanner provides Fastapi-specific findings with severity levels based on the potential impact. For example, header injection in authentication endpoints receives higher severity than in informational endpoints.
Running middleBrick against your Fastapi application is straightforward:
middlebrick scan https://api.yourfastapi.com
The scanner tests all exposed endpoints, including those with Fastapi's automatic OpenAPI documentation. It identifies endpoints that construct headers from user input and provides specific remediation guidance.
For continuous monitoring, the middleBrick GitHub Action can scan your Fastapi API in CI/CD pipelines:
- name: middleBrick API Security Scan
uses: middleBrick/middlebrick-action@v1
with:
api_url: https://staging.yourfastapi.com
fail_below_score: 80
This integration catches header injection vulnerabilities before they reach production, failing builds when security scores drop below your threshold.
middleBrick's Fastapi-specific detection includes LLM/AI security scanning for endpoints that might serve AI/ML models, testing for system prompt leakage and prompt injection vulnerabilities that could be combined with header injection attacks.
Fastapi-Specific Remediation
Remediating header injection in Fastapi requires proper input validation and header sanitization. Fastapi provides several mechanisms to prevent these vulnerabilities.
The most effective approach is using Fastapi's built-in validation with Pydantic models:
from fastapi import FastAPI, Request, Header
from pydantic import BaseModel, constr
from fastapi.responses import JSONResponse
app = FastAPI()
class UserID(BaseModel):
user_id: constr(min_length=1, max_length=100, strip_whitespace=True)
@app.get("/api/user/{user_id}")
async def get_user(request: Request, user_id: str):
# Validate and sanitize user_id
if "\r" in user_id or "\n" in user_id:
raise HTTPException(status_code=400, detail="Invalid user ID")
# Safe: user_id is validated before use
return JSONResponse(
content={"message": "User data"},
headers={"X-User-ID": user_id}
)This pattern validates that the user_id contains no newline characters before using it in headers. Fastapi's Pydantic integration makes this validation straightforward.
For dependency injection scenarios, sanitize header values before use:
from fastapi import Depends
def get_user_agent(request: Request) -> str:
user_agent = request.headers.get("user-agent", "unknown")
# Sanitize: remove newline characters
if "\r" in user_agent or "\n" in user_agent:
raise HTTPException(status_code=400, detail="Invalid user agent")
return user_agent
@app.get("/api/data")
async def get_data(user_agent: str = Depends(get_user_agent)):
return JSONResponse(
content={"data": "sensitive"},
headers={"X-User-Agent": user_agent}
)Fastapi's exception handling ensures that invalid requests are rejected before header construction occurs.
For path parameters, use Fastapi's type validation with custom sanitization:
from fastapi import HTTPException
@app.get("/api/{path_param}/data")
async def get_data(path_param: str):
# Sanitize path parameter
if "\r" in path_param or "\n" in path_param:
raise HTTPException(status_code=400, detail="Invalid path parameter")
return JSONResponse(
content={"data": "sensitive"},
headers={"X-Path-Param": path_param}
)Fastapi's middleware can also sanitize all outgoing headers:
from fastapi import Request, Response
from fastapi.middleware.base import BaseHTTPMiddleware
class HeaderSanitizationMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
response = await call_next(request)
# Sanitize all headers
for header_name in response.headers.keys():
if "\r" in header_name or "\n" in header_name:
del response.headers[header_name]
return response
app.add_middleware(HeaderSanitizationMiddleware)This middleware provides defense-in-depth by sanitizing headers at the response level, catching any header injection that bypasses earlier validation.