Out Of Bounds Read in Fastapi
How Out Of Bounds Read Manifests in Fastapi
Out Of Bounds Read vulnerabilities in FastAPI applications typically occur when request data is processed without proper validation of its boundaries. FastAPI's automatic request parsing and validation can create false confidence, leading developers to assume all inputs are safe when they may not be.
A common manifestation appears in FastAPI's dependency injection system. Consider a dependency that retrieves a user by ID from a database:
from fastapi import Depends, HTTPException
from sqlalchemy.orm import Session
from database import get_db
from models import User
def get_user(user_id: int, db: Session = Depends(get_db)):
user = db.query(User).filter(User.id == user_id).first()
if user is None:
raise HTTPException(status_code=404, detail="User not found")
return user
@app.get("/users/{user_id}")
async def read_user(user: User = Depends(get_user)):
return user.dict()This pattern is vulnerable to Out Of Bounds Read if the database query returns unexpected results. An attacker could craft requests that cause the ORM to return partial objects or None values that are then accessed without proper null checks.
FastAPI's Pydantic models can also introduce Out Of Bounds Read vulnerabilities. When using model parsing with arbitrary data:
from pydantic import BaseModel
class UserUpdate(BaseModel):
name: str
email: str
@app.put("/users/{user_id}")
async def update_user(user_id: int, update: UserUpdate):
user = get_user_from_db(user_id) # Assume this function exists
user.name = update.name
user.email = update.email
# Vulnerable: no bounds checking on update fields
return userThe vulnerability here is that Pydantic's parsing doesn't guarantee all fields are present or valid. If the update object is malformed or contains unexpected data, accessing fields without validation can lead to Out Of Bounds Read conditions.
Another FastAPI-specific pattern involves streaming responses where boundary checks are critical:
@app.get("/stream/{start}/{end}")
async def stream_data(start: int, end: int):
data = await get_large_dataset()
return StreamingResponse(
(data[i] for i in range(start, end)),
media_type="text/plain"
)
# Vulnerable: no validation that start/end are within data boundsWithout validating that start and end are within the actual dataset bounds, this endpoint can attempt to read beyond the available data, causing Out Of Bounds Read vulnerabilities.
FastAPI-Specific Detection
Detecting Out Of Bounds Read vulnerabilities in FastAPI requires understanding both the framework's request processing pipeline and common attack patterns. middleBrick's black-box scanning approach is particularly effective for FastAPI applications because it tests the actual runtime behavior without requiring source code access.
When scanning a FastAPI endpoint, middleBrick examines the OpenAPI specification generated by the framework to understand the expected input parameters and their types. For the streaming endpoint example above, middleBrick would identify that start and end are integer parameters and test boundary conditions:
# middleBrick would test patterns like:
# Negative indices
response = requests.get(f"{base_url}/stream/-10/5")
# Indices beyond dataset size
response = requests.get(f"{base_url}/stream/999999/1000000")
# End before start
response = requests.get(f"{base_url}/stream/10/5")middleBrick's Property Authorization check specifically looks for these boundary violations in FastAPI applications. The scanner sends crafted requests that attempt to access data outside expected bounds and analyzes the responses for signs of information disclosure or application crashes.
For Pydantic model vulnerabilities, middleBrick's Input Validation check examines how FastAPI handles malformed or incomplete request bodies. The scanner tests scenarios where required fields are missing or contain unexpected data types:
# Testing Pydantic model vulnerabilities
malformed_payload = {"name": "test"} # Missing email field
response = requests.put(f"{base_url}/users/1", json=malformed_payload)
# Testing with unexpected data types
invalid_payload = {"name": 12345, "email": ["invalid"]}
response = requests.put(f"{base_url}/users/1", json=invalid_payload)middleBrick's GitHub Action integration makes it easy to add these FastAPI-specific security checks to your CI/CD pipeline. The action can be configured to scan your staging API before deployment:
- name: FastAPI Security Scan
uses: middleBrick/middleBrick-action@v1
with:
url: http://staging-api.company.com
fail-on-severity: high
output-format: jsonThe CLI tool provides another way to scan FastAPI applications during development. You can scan your local development server to catch Out Of Bounds Read vulnerabilities before they reach production:
middlebrick scan http://localhost:8000 --output report.json --format jsonFastAPI-Specific Remediation
Remediating Out Of Bounds Read vulnerabilities in FastAPI requires a combination of proper input validation, defensive programming, and leveraging FastAPI's built-in validation features. The most effective approach is to implement comprehensive bounds checking at the API layer.
For the streaming endpoint vulnerability, FastAPI's path parameter validation can be enhanced with custom validators:
from fastapi import Path, HTTPException
from pydantic import validator
from typing import Annotated
async def validate_range(*, value: int, min_value: int, max_value: int):
if not (min_value <= value <= max_value):
raise HTTPException(
status_code=400,
detail=f"Value must be between {min_value} and {max_value}"
)
return value
@app.get("/stream/{start}/{end}")
async def stream_data(
start: Annotated[int, Path(ge=0)] = Path(..., description="Start index"),
end: Annotated[int, Path(ge=1)] = Path(..., description="End index")
):
data = await get_large_dataset()
data_length = len(data)
# Validate bounds
if start >= data_length or end > data_length or start >= end:
raise HTTPException(
status_code=400,
detail=f"Range must be within 0-{data_length-1}"
)
return StreamingResponse(
(data[i] for i in range(start, end)),
media_type="text/plain"
)This approach uses FastAPI's path parameter validation combined with explicit bounds checking to prevent Out Of Bounds Read attacks.
For Pydantic model vulnerabilities, use model validation to ensure all required fields are present and properly typed:
from pydantic import BaseModel, ValidationError, validator
class UserUpdate(BaseModel):
name: str
email: str
@validator('email')
def email_must_be_valid(cls, v):
if not v or '@' not in v:
raise ValueError('Invalid email address')
return v
@app.put("/users/{user_id}")
async def update_user(user_id: int, update: UserUpdate):
user = get_user_from_db(user_id)
if user is None:
raise HTTPException(status_code=404, detail="User not found")
user.name = update.name
user.email = update.email
return userThe key improvement here is that Pydantic's model validation ensures the update object is complete and valid before it reaches your business logic.
For database query vulnerabilities, always validate that query results exist before accessing them:
from fastapi import Depends, HTTPException
from sqlalchemy.orm import Session
def get_user(user_id: int, db: Session = Depends(get_db)):
user = db.query(User).filter(User.id == user_id).first()
if user is None:
raise HTTPException(status_code=404, detail="User not found")
return user
@app.get("/users/{user_id}")
async def read_user(user: User = Depends(get_user)):
# Safe: user is guaranteed to exist due to dependency injection
return user.dict()middleBrick's continuous monitoring feature in the Pro plan can help verify that these remediations remain effective over time. The scanner will periodically test your FastAPI endpoints for Out Of Bounds Read vulnerabilities and alert you if new issues are discovered.