Crlf Injection in Fastapi with Api Keys
Crlf Injection in Fastapi with Api Keys — how this specific combination creates or exposes the vulnerability
Crlf Injection occurs when user-controlled data is reflected in HTTP headers without sanitization, allowing an attacker to inject carriage return (CR, \r) and line feed (\n) sequences. In Fastapi, this commonly arises when API keys or other header values are used directly in responses or downstream requests without validation. Consider a service that accepts an API key via an HTTP header and echoes it into a custom response header or includes it in an outbound request. If the API key contains \r\n sequences, an attacker can split the header chain and inject additional headers, such as Location or Set-Cookie, leading to HTTP response splitting, open redirects, or header-based smuggling.
When API keys are passed between services, for example from an API gateway to a backend, unescaped newlines in key values can break header parsing logic on intermediate proxies or frameworks. An attacker who can influence the API key—perhaps by registering or guessing a weak key—can place \r\n into the key and then cause the server to append malicious headers like X-Injected: 1. In Fastapi, this can happen if developer code does not sanitize header values before using them in Response.headers or when constructing requests with libraries such as httpx or requests. Even though Fastapi relies on Starlette for request parsing, header injection is not automatically prevented; the framework trusts developer implementation to keep header values safe.
In the context of automated scanning, tools like middleBrick test for Crlf Injection by submitting inputs containing \r\n sequences in parameters, cookies, and headers—including API key locations—and checking whether injected content appears in subsequent responses or outbound requests. The presence of unvalidated API keys in headers is a common condition that raises the risk score for Injection and Header Manipulation checks. Developers should treat API keys as untrusted input when they are reflected anywhere in the protocol, even if the key is expected to be opaque, because format assumptions can be violated by an attacker.
Api Keys-Specific Remediation in Fastapi — concrete code fixes
Remediation focuses on validating and sanitizing any user-influenced data before it reaches headers, especially API keys. Do not rely on framework defaults; explicitly reject or encode \r and \n in header values. Below are two concrete patterns for safe handling in Fastapi.
1. Reject unsafe characters in API key validation
Use a dependency or explicit validation to ensure API keys do not contain CR or LF. This prevents attacker-controlled keys from entering the response or request chain.
from fastapi import Fastapi, Header, HTTPException, Request
import re
app = Fastapi()
# Reject CR/LF in API key values
SAFE_KEY_RE = re.compile(r'^[^\r\n]+$')
def validate_api_key(api_key: str):
if not SAFE_KEY_RE.match(api_key):
raise HTTPException(status_code=400, detail="Invalid API key format")
return api_key
@app.get("/items")
async def read_items(request: Request, api_key: str = Header(...)):
key = validate_api_key(api_key)
# Use the validated key safely; do not concatenate it into headers without escaping
return {"key_valid": True}
2. Sanitize before setting response or request headers with httpx
If you forward API keys to downstream services or reflect them in custom headers, sanitize by removing or encoding problematic characters. Do not directly assign user input into Response.headers.
from fastapi import Fastapi, Header
import httpx
import re
app = Fastapi()
def safe_header_value(value: str) -> str:
# Remove CR/LF to prevent header injection
return re.sub(r'[\r\n]', '', value)
@app.post("/forward")
async def forward(api_key: str = Header(...)):
safe_key = safe_header_value(api_key)
headers = {"X-API-Key": safe_key}
async with httpx.AsyncClient() as client:
# Safe: headers contain no newline characters
resp = await client.get("https://backend.example.com/data", headers=headers)
return {"status": resp.status_code}
General guidance
- Treat API keys as opaque but untrusted when reflected in headers.
- Apply allow-lists or strict regex patterns for key formats rather than trying to block only dangerous characters.
- If you accept configuration values that may be used in header construction, validate them at the boundary and log violations.