Mass Assignment in Fastapi with Hmac Signatures
Mass Assignment in Fastapi with Hmac Signatures — how this specific combination creates or exposes the vulnerability
Mass assignment occurs when an API binds incoming JSON data directly to a model or dictionary without filtering which fields are accepted. In Fastapi, this commonly happens when using Body(...) or Depends with Pydantic models that include fields not intended for client assignment, such as id, role, is_admin, or created_at. When Hmac Signatures are used to verify the integrity of a request — typically by including a signature in a header (e.g., X-API-Signature) computed over selected payload fields — a mismatch between the signed subset and the deserialized model can lead to privilege escalation or data manipulation if unchecked fields are applied after verification.
For example, an attacker may omit a signed field that the server excludes from the signature but includes in the Pydantic model. The server validates the Hmac correctly (because the signed data matches), yet applies the unvalidated fields directly to the model, effectively bypassing intended immutability. This is common when using nested models or when field aliases differ between the signature computation and model binding. The vulnerability is particularly dangerous when combined with operations that modify sensitive resources, such as updating user roles or transferring ownership, because the server trusts the request body beyond the signed portion.
In Fastapi, this risk is amplified when using automatic dependency injection that merges query parameters, headers, and body without explicit field whitelisting. Even if the Hmac covers the raw JSON string, developers might deserialize into a broader model before checking authorization, allowing mass assignment to fields that should be server-controlled. Real-world attack patterns like those in the OWASP API Top 10 — specifically Broken Object Level Authorization (BOLA) — intersect with mass assignment when over-permissive models enable horizontal or vertical privilege escalation.
Hmac Signatures-Specific Remediation in Fastapi — concrete code fixes
To securely use Hmac Signatures in Fastapi and prevent mass assignment, enforce strict field-level validation and ensure the signature covers all and only the fields that should be trusted. Use Pydantic models with extra='forbid' to reject unexpected fields, and compute the signature over a canonical subset of request data — never the entire mutable model. Validate the signature before binding to sensitive models, and apply transformations only after verification.
Example: Secure Hmac verification with explicit field selection
from fastapi import FastAPI, Header, HTTPException, status
from pydantic import BaseModel, ConfigDict
import hmac
import hashlib
import json
app = FastAPI()
SECRET_KEY = b"super-secret-key"
class UserUpdateData(BaseModel):
model_config = ConfigDict(extra='forbid')
email: str
name: str
def compute_signature(data: dict) -> str:
payload = json.dumps(data, separators=(',', ':'), sort_keys=True)
return hmac.new(SECRET_KEY, payload.encode(), hashlib.sha256).hexdigest()
@app.put("/users/{user_id}")
async def update_user(
user_id: int,
x_api_signature: str = Header(...),
body: dict
):
# 1. Verify signature over explicit, allowed fields only
expected = compute_signature(body)
if not hmac.compare_digest(expected, x_api_signature):
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid signature")
# 2. Parse and validate against a strict model
data = UserUpdateData(**body)
# 3. Proceed with safe update using validated data
return {"user_id": user_id, "email": data.email, "name": data.name}
This pattern ensures that only email and name are accepted, while extra fields are rejected by the model. The signature is computed over the raw JSON payload containing exactly those fields, preventing an attacker from injecting additional parameters that would pass Hmac validation but be applied after deserialization.
Example: Rejecting unsigned mutable fields with dependency injection
from fastapi import Depends, FastAPI
from typing import Annotated
def get_safe_body(body: dict) -> dict:
# Enforce schema and forbid extra fields at dependency level
return UserUpdateData(**body).model_dump()
SafeBody = Annotated[dict, Depends(get_safe_body)]
@app.post("/items")
async def create_item(
x_api_signature: str = Header(...),
body: SafeBody = Depends()
):
# Signature verification omitted for brevity
return {"received": body}
By combining schema enforcement, canonical serialization, and early signature validation, you mitigate mass assignment risks even when Hmac Signatures are used. This approach aligns with secure coding practices for API integrity and helps satisfy compliance mappings to OWASP API Security Top 10 and related standards.
Related CWEs: propertyAuthorization
| CWE ID | Name | Severity |
|---|---|---|
| CWE-915 | Mass Assignment | HIGH |
Frequently Asked Questions
Can Hmac Signatures alone prevent mass assignment in Fastapi?
extra='forbid') and explicit field whitelisting to prevent mass assignment.