Data Exposure in Fastapi with Dynamodb
Data Exposure in Fastapi with Dynamodb — how this specific combination creates or exposes the vulnerability
When a Fastapi application interacts with Amazon DynamoDB, data exposure risks arise from a combination of framework behavior and DynamoDB access patterns. Fastapi’s automatic request parsing and dependency injection can inadvertently pass excessive or unvalidated parameters to DynamoDB operations, leading to unintended data retrieval or exposure. For example, if an endpoint uses user-supplied query parameters directly in a DynamoDB KeyConditionExpression or FilterExpression, missing validation may allow an attacker to traverse partitions or scan broader datasets than intended.
In DynamoDB, data exposure often occurs when responses include sensitive attributes that should be omitted. A typical DynamoDB response returns all item attributes by default. If a Fastapi endpoint returns the full DynamoDB response to the client without pruning sensitive fields (such as internal identifiers, credentials, or personal data), attackers can harvest information. This is especially risky when endpoints use unauthenticated access or weak authorization checks, as DynamoDB’s fine-grained IAM policies may not restrict attribute-level exposure at the application layer.
Another vector involves pagination and scan operations. Fastapi routes that invoke Scan or unkeyed Query operations on DynamoDB can expose entire tables or large subsets if pagination tokens or limit parameters are not tightly controlled. Attackers may abuse missing rate limiting or insufficient filtering to enumerate data. Since DynamoDB stores nested and unstructured data, sensitive fields embedded in nested maps or lists may be returned in full unless explicitly projected out. The combination of Fastapi’s lenient request handling and DynamoDB’s default full-attribute responses creates a scenario where sensitive data is unintentionally surfaced through otherwise functional API endpoints.
Compliance mappings highlight the severity: data exposure violates multiple controls in the OWASP API Top 10 (e.g., Broken Object Level Authorization), PCI-DSS (protection of cardholder data), SOC2 (confidentiality controls), HIPAA (protected health information), and GDPR (personal data exposure). Because DynamoDB does not inherently redact fields, responsibility falls to the application layer. Fastapi endpoints must explicitly control what leaves the process, using projection expressions and response filtering to ensure only intended data is serialized and sent to clients.
Dynamodb-Specific Remediation in Fastapi — concrete code fixes
To mitigate data exposure when using DynamoDB with Fastapi, apply strict request validation, use DynamoDB projection expressions, and filter responses before serialization. Below are concrete, working examples that demonstrate secure patterns.
1. Validate and parameterize queries
Never concatenate user input into DynamoDB expressions. Use typed parameters and validate identifiers before use.
from fastapi import FastAPI, HTTPException, Depends
import boto3
from pydantic import BaseModel
import re
app = FastAPI()
dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
table = dynamodb.Table('users')
class UserQuery(BaseModel):
user_id: str
def validate_user_id(user_id: str) -> str:
if not re.match(r'^[a-zA-Z0-9_-]{1,64}$', user_id):
raise ValueError('Invalid user_id')
return user_id
@app.get('/users/{user_id}')
def get_user(user_id: str, query: UserQuery = Depends(UserQuery)):
safe_id = validate_user_id(query.user_id)
try:
response = table.get_item(
Key={'user_id': safe_id},
ProjectionExpression='user_id,email,status' # limit attributes
)
item = response.get('Item')
if not item:
raise HTTPException(status_code=404, detail='User not found')
return item
except Exception as e:
raise HTTPException(status_code=500, detail='Database error')
2. Use FilterExpression to exclude sensitive attributes
DynamoDB does not support attribute-level read permissions via IAM alone at runtime; filter in application code.
import boto3
from fastapi import Depends
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('profiles')
# Only return safe, non-sensitive fields
response = table.scan(
FilterExpression='attribute_exists(public_name) AND NOT contains(attributes, :secret)',
ExpressionAttributeValues={':secret': 'internal'},
ProjectionExpression='id,public_name,created_at'
)
items = response.get('Items', [])
3. Avoid Scan; prefer Query with KeyConditionExpression
Scan operations expose all items. Use Query with indexed attributes and strict KeyConditionExpression.
response = table.query(
KeyConditionExpression='pk = :pkval AND sk BETWEEN :start AND :end',
ExpressionAttributeValues={':pkval': 'user#123', ':start': 'profile#2024', ':end': 'profile#2025'},
ProjectionExpression='sk,display_name,email' # limit returned data
)
4. Redact sensitive fields in Fastapi response models
Define output models that exclude sensitive fields to prevent accidental leakage through serialization.
from pydantic import BaseModel
from typing import List
class UserOut(BaseModel):
user_id: str
email: str
status: str
class Config:
orm_mode = True
@app.get('/users', response_model=List[UserOut])
def list_users():
response = table.scan(ProjectionExpression='user_id,email,status')
return response.get('Items', [])
5. Enforce attribute-level projection in all DynamoDB calls
Always use ProjectionExpression to restrict returned attributes. Combine with IAM policies that limit scope, but assume application-layer filtering is essential.
# Explicitly list allowed attributes
response = table.get_item(
Key={'user_id': 'u123'},
ProjectionExpression='user_id,email,profile_data.name,profile_data.locale'
)
These patterns reduce the risk of data exposure by ensuring DynamoDB returns only necessary attributes, that inputs are validated, and that sensitive fields are never serialized to the client. Combined with Fastapi’s dependency injection for authorization, they form a practical defense against common data leakage scenarios.
Related CWEs: dataExposure
| CWE ID | Name | Severity |
|---|---|---|
| CWE-200 | Exposure of Sensitive Information | HIGH |
| CWE-209 | Error Information Disclosure | MEDIUM |
| CWE-213 | Exposure of Sensitive Information Due to Incompatible Policies | HIGH |
| CWE-215 | Insertion of Sensitive Information Into Debugging Code | MEDIUM |
| CWE-312 | Cleartext Storage of Sensitive Information | HIGH |
| CWE-359 | Exposure of Private Personal Information (PII) | HIGH |
| CWE-522 | Insufficiently Protected Credentials | CRITICAL |
| CWE-532 | Insertion of Sensitive Information into Log File | MEDIUM |
| CWE-538 | Insertion of Sensitive Information into Externally-Accessible File | HIGH |
| CWE-540 | Inclusion of Sensitive Information in Source Code | HIGH |