HIGH crlf injectionfastapi

Crlf Injection in Fastapi

How Crlf Injection Manifests in Fastapi

Crlf Injection in Fastapi occurs when untrusted user input containing carriage return (CR) or line feed (LF) characters is incorporated into HTTP headers or other protocol elements without proper sanitization. Fastapi applications are particularly vulnerable because they often use dependency injection and automatic request parsing, which can inadvertently pass raw user data to header construction.

Consider this common Fastapi pattern:

from fastapi import FastAPI, Request

app = FastAPI()

@app.get("/user")
async def get_user(request: Request):
    user_agent = request.headers.get("user-agent")
    response = JSONResponse(
        content={"message": "Hello!"},
        headers={"X-User-Agent": user_agent}
    )
    return response

An attacker could send a request with a crafted User-Agent header:

User-Agent: Mozilla/5.0

Set-Cookie: session=malicious; HttpOnly

Content-Type: text/html

This would result in the response containing:

HTTP/1.1 200 OK
X-User-Agent: Mozilla/5.0
Set-Cookie: session=malicious; HttpOnly
Content-Type: text/html

{"message": "Hello!"}

The attacker has successfully injected new headers into the response, potentially stealing cookies or manipulating client behavior.

Fastapi's dependency injection system can exacerbate this issue. When using Path, Query, or Header parameters, developers might assume Fastapi automatically sanitizes input:

from fastapi import FastAPI, Header

app = FastAPI()

@app.get("/report")
async def generate_report(report_id: str = Header(...)):
    # report_id comes directly from the header
    # without sanitization
    return JSONResponse(
        content={"report": f"Report {report_id} generated"},
        headers={"X-Report-ID": report_id}
    )

Another Fastapi-specific vulnerability arises with response_model and response headers. When using Pydantic models with custom headers:

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class ReportResponse(BaseModel):
    report_id: str
    
    class Config:
        @staticmethod
        def schema_extra(schema, model):
            schema.update({
                "headers": {
                    "X-Report-ID": "{{report_id}}"
                }
            })

@app.post("/reports", response_model=ReportResponse)
async def create_report(report: ReportRequest):
    return ReportResponse(report_id=report.id)

If report.id contains CRLF characters, they can be injected into the response headers through the schema_extra configuration.

Fastapi-Specific Detection

Detecting CRLF Injection in Fastapi applications requires both static analysis and dynamic testing. For static analysis, scan your codebase for patterns where user input flows into header construction or response manipulation.

Using middleBrick's CLI tool, you can scan your Fastapi endpoints for CRLF vulnerabilities:

npx middlebrick scan https://your-fastapi-app.com --category "Input Validation"

middleBrick's scanner specifically tests for CRLF injection by sending payloads containing %0D%0A sequences and monitoring for header injection in responses. The scanner evaluates 12 security categories including Authentication, BOLA/IDOR, and Input Validation, with findings mapped to OWASP API Top 10.

For manual testing in Fastapi, use curl to test header injection:

curl -v -H "User-Agent: Mozilla/5.0%0D%0ASet-Cookie:%20malicious%3Dtrue%3B%20HttpOnly%0D%0AContent-Type:%20text/html" \
     https://your-fastapi-app.com/user

Watch for injected headers in the response. If you see Set-Cookie or other headers appear that you didn't program, you have a CRLF vulnerability.

Fastapi's built-in logging can help detect suspicious patterns. Enable detailed logging and monitor for unusual header patterns:

from fastapi import FastAPI
import logging

app = FastAPI()

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

@app.middleware("http")
async def crlf_detection_middleware(request: Request, call_next):
    for header, value in request.headers.items():
        if '\r' in value or '\n' in value:
            logger.warning(f"CRLF characters detected in header {header}: {value}")
    response = await call_next(request)
    return response

middleBrick's continuous monitoring (Pro plan) can automatically scan your Fastapi endpoints on a schedule, alerting you when new CRLF vulnerabilities are detected in production APIs.

Fastapi-Specific Remediation

Remediating CRLF Injection in Fastapi requires input sanitization before header construction. Fastapi provides several approaches to prevent this vulnerability.

The most robust solution is to sanitize input using Python's built-in capabilities:

import re
from fastapi import FastAPI, Request, HTTPException

app = FastAPI()

def sanitize_crlf(input_str: str) -> str:
    """Remove CR and LF characters from input"""
    if not input_str:
        return input_str
    # Remove carriage return and line feed characters
    sanitized = re.sub(r'[
]', '', input_str)
    return sanitized

@app.get("/user")
async def get_user(request: Request):
    user_agent = request.headers.get("user-agent", "")
    sanitized_agent = sanitize_crlf(user_agent)
    
    response = JSONResponse(
        content={"message": "Hello!"},
        headers={"X-User-Agent": sanitized_agent}
    )
    return response

For header parameters specifically, Fastapi's Header class allows validation:

from fastapi import FastAPI, Header, HTTPException
import re

app = FastAPI()

def validate_no_crlf(value: str):
    if '\r' in value or '\n' in value:
        raise HTTPException(
            status_code=400,
            detail="Header contains invalid characters"
        )
    return value

@app.get("/report")
async def generate_report(
    report_id: str = Header(..., regex=r'^[a-zA-Z0-9_-]+$')
):
    # The regex ensures only alphanumeric and common safe characters
    return JSONResponse(
        content={"report": f"Report {report_id} generated"},
        headers={"X-Report-ID": report_id}
    )

For response models with custom headers, validate before serialization:

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class ReportResponse(BaseModel):
    report_id: str

@app.post("/reports", response_model=ReportResponse)
async def create_report(report: ReportRequest):
    # Sanitize before returning
    sanitized_id = sanitize_crlf(report.id)
    return ReportResponse(report_id=sanitized_id)

Implement a global middleware to sanitize all headers:

from fastapi import FastAPI, Request, Response

app = FastAPI()

def sanitize_headers(headers: dict) -> dict:
    sanitized = {}
    for key, value in headers.items():
        if isinstance(value, str):
            sanitized[key] = sanitize_crlf(value)
        else:
            sanitized[key] = value
    return sanitized

@app.middleware("http")
async def sanitize_middleware(request: Request, call_next):
    # Sanitize request headers
    sanitized_headers = sanitize_headers(request.headers)
    
    response = await call_next(request)
    
    # Sanitize response headers
    response.headers = sanitize_headers(response.headers)
    
    return response

For production Fastapi applications, combine input validation, sanitization, and monitoring. middleBrick's Pro plan includes continuous scanning that can detect if CRLF vulnerabilities reappear after remediation, ensuring your fixes remain effective over time.

Frequently Asked Questions

How does middleBrick detect CRLF Injection in Fastapi applications?
middleBrick's scanner sends HTTP requests containing %0D%0A (CRLF) sequences to your Fastapi endpoints and analyzes responses for injected headers. The scanner runs 12 security checks in parallel, including Input Validation, and provides severity ratings with remediation guidance. No credentials or agents are required—just submit your Fastapi API URL for a 5-15 second scan.
Can CRLF Injection in Fastapi lead to authentication bypass?
Yes. CRLF Injection can be used to inject Set-Cookie headers that override authentication tokens, inject Location headers for open redirect attacks, or manipulate Cache-Control headers. In Fastapi applications, this is particularly dangerous when user input flows directly into response headers without sanitization, potentially allowing attackers to hijack sessions or bypass security controls.