Header Injection in Fastapi with Dynamodb
Header Injection in Fastapi with Dynamodb — how this specific combination creates or exposes the vulnerability
Header Injection occurs when user-controlled data is reflected into HTTP response headers without validation or encoding. In a Fastapi application that interacts with DynamoDB, this typically happens when request parameters (such as query strings or JSON bodies) are used to construct or influence response headers— for example, setting a custom header like x-user-id or x-request-id from input before returning a DynamoDB query result. Because Fastapi does not automatically sanitize header values, an attacker can supply newline characters (e.g., \r\n) to inject additional headers, a technique often referred to as CRLF injection.
When the injected header manipulates caching or security directives, it can lead to HTTP response splitting, which may allow an attacker to poison caches, perform cross-user tampering, or inject content that is interpreted by downstream proxies or browsers. In the context of DynamoDB, the risk is not in the database itself but in how the application handles data retrieved from DynamoDB or user input that eventually reaches response headers. For instance, if a Fastapi endpoint accepts a user ID, queries DynamoDB for profile information, and then sets a header such as x-profile-owner: {user_id} without sanitization, an attacker can inject newline sequences to append headers like Set-Cookie: or Location:, altering the intended response flow.
An additional concern specific to DynamoDB is the handling of item attributes that may contain unexpected characters. If a DynamoDB-stored attribute (such as a custom header name or value) is used directly in the Fastapi response without validation, and that attribute includes carriage returns or line feeds, the server may inadvertently introduce header injection vectors when constructing responses. This is especially relevant when using DynamoDB as a source for configuration or metadata that influence HTTP behavior. The combination of Fastapi’s flexible header handling and DynamoDB’s schema-less design increases the importance of strict input validation and output encoding at the application boundary.
Dynamodb-Specific Remediation in Fastapi — concrete code fixes
To mitigate Header Injection in Fastapi when working with DynamoDB, you must validate and sanitize any data that flows into response headers, whether it originates from user input or from DynamoDB item attributes. Below are concrete, secure patterns for Fastapi endpoints that query DynamoDB using the AWS SDK for Python (Boto3).
First, enforce strict allowlists for header names and use canonical header names provided by Fastapi. Never directly assign user-controlled strings to header keys. For header values, remove or encode newline characters and other control characters. Here is a secure Fastapi endpoint example:
from fastapi import Fastapi, Request, Header
import boto3
from botocore.exceptions import ClientError
app = Fastapi()
dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
table = dynamodb.Table('Profiles')
@app.get('/profile')
async def get_profile(x_user_id: str):
# Validate input: allow only alphanumeric and safe characters
if not x_user_id.replace('_', '').replace('-', '').isalnum():
raise ValueError('Invalid user ID')
try:
response = table.get_item(Key={'user_id': x_user_id})
item = response.get('Item')
if not item:
return {'error': 'not found'}
# Safe usage: sanitize any item field used in headers
display_name = item.get('display_name', '').replace('\r', '').replace('\n', '')
return {
'user_id': item['user_id'],
'display_name': display_name
}
except ClientError as e:
raise HTTPException(status_code=500, detail='Database error')
In the response construction, avoid setting headers derived from DynamoDB item attributes directly. If you must set custom headers, explicitly filter content:
from fastapi import Response
def build_safe_header(value: str) -> str:
# Remove CR and LF to prevent header injection
return value.replace('\r', '').replace('\n', '')
@app.get('/items/{item_id}')
async def read_item(item_id: str, response: Response):
try:
rec = table.get_item(Key={'id': item_id})
item = rec.get('Item', {})
safe_meta = build_safe_header(item.get('meta', ''))
response.headers['X-Item-Meta'] = safe_meta
return item
except ClientError:
raise HTTPException(status_code=500, detail='Error')
Additionally, configure Fastapi to log warnings when headers contain suspicious characters, and apply global middleware to reject requests that contain newline characters in URL paths or query parameters. These measures reduce the likelihood that DynamoDB-sourced or user-supplied data can influence HTTP message parsing.