GuardAPI Logo
GuardAPI

Fix Mass Assignment in FastAPI

Mass Assignment (CWE-915) in FastAPI occurs when you blindly unpack a Pydantic model or a dictionary into a database object. If your input schema includes internal fields like 'is_admin', 'role', or 'balance', an attacker can modify their privilege level by simply adding those keys to the JSON request body. Stop trusting the client; start whitelisting your inputs.

The Vulnerable Pattern

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class UserProfile(BaseModel): username: str email: str is_admin: bool = False # SENSITIVE FIELD

@app.put(‘/profile/{user_id}’) async def update_profile(user_id: int, profile: UserProfile): db_user = await get_db_user(user_id) # VULNERABLE: Blindly unpacking the entire model into the DB object # Attacker sends: {“username”: “hacker”, “is_admin”: true} for key, value in profile.dict().items(): setattr(db_user, key, value) await db_user.save() return {“status”: “success”}

The Secure Implementation

The vulnerability is mitigated by implementing 'Schema Separation'. Instead of using a single model for both database representation and API input, create dedicated Pydantic models (DTOs) for specific operations like 'UserUpdate' or 'UserCreate'. These models must only contain fields that a user is explicitly allowed to change. By using '.dict(exclude_unset=True)', you ensure that only the fields provided in the request—and validated by the schema—are updated in the persistence layer, effectively creating a whitelist that blocks unauthorized field modification.

from fastapi import FastAPI
from pydantic import BaseModel, Field

app = FastAPI()

SECURE: Define a specific DTO for updates that excludes sensitive fields

class UserUpdate(BaseModel): username: str | None = Field(None, max_length=50) email: str | None = Field(None)

@app.put(‘/profile/{user_id}’) async def update_profile(user_id: int, update_data: UserUpdate): db_user = await get_db_user(user_id) # SECURE: Only fields defined in UserUpdate are processed. # Even if the attacker sends ‘is_admin’, Pydantic will ignore it. data = update_data.dict(exclude_unset=True) for key, value in data.items(): setattr(db_user, key, value) await db_user.save() return {“status”: “success”}

System Alert • ID: 4267
Target: FastAPI API
Potential Vulnerability

Your FastAPI API might be exposed to Mass Assignment

74% of FastAPI apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.

RUN FREE SECURITY DIAGNOSTIC
GuardLabs Engine: ONLINE

Free Tier • No Credit Card • Instant Report

Verified by Ghost Labs Security Team

This content is continuously validated by our automated security engine and reviewed by our research team. Ghost Labs analyzes over 500+ vulnerability patterns across 40+ frameworks to provide up-to-date remediation strategies.