Excessive Data Exposure in Fastapi with Hmac Signatures
Excessive Data Exposure in Fastapi with Hmac Signatures — how this specific combination creates or exposes the vulnerability
Excessive Data Exposure occurs when an API returns more information than necessary for a given operation, such as full database records, internal identifiers, or sensitive fields that should remain hidden. In Fastapi applications that rely on Hmac Signatures for request integrity, the vulnerability can be amplified when endpoints expose data beyond what the client is authorized to see, and the Hmac verification does not enforce field-level or row-level authorization.
Consider a typical pattern where a Fastapi endpoint validates an Hmac signature to ensure the request has not been tampered with, but then returns a complete database object without checking whether the requesting user is allowed to view sensitive attributes such as email, internal IDs, or payment details. Because the Hmac process only verifies that the payload was not altered, developers may mistakenly assume that the data exposure risk is mitigated, when in reality the signature verification and data exposure controls are independent concerns. An attacker who can make authenticated requests (or intercept a valid signed request for a different user) may receive responses that include private information not intended for their role or scope.
For example, imagine an endpoint that lists user profiles and uses Hmac Signatures to verify the integrity of query parameters like user_id and timestamp. If the endpoint returns the full user record—including fields such as is_admin, password_hash, or external_provider_id—without applying additional authorization checks, the response may disclose data that should be restricted. Even when the Hmac signature is valid, the API can still leak data because signature validation does not equate to authorization. This is especially risky when the API supports filtering or pagination and returns nested objects or related resources that were not explicitly requested.
In the context of middleBrick’s security checks, this scenario maps to the Property Authorization and Data Exposure categories. The scanner tests whether responses contain information that should be subject to access control, such as sensitive fields or identifiers that enable horizontal or vertical privilege escalation. Because Fastapi endpoints often serialize SQLAlchemy models or Pydantic schemas directly, it is easy to expose internal attributes unless the response model is explicitly constrained. The presence of Hmac Signatures does not reduce the risk; it only ensures the request has not been modified, not that the data returned is appropriate for the caller.
To illustrate, a developer might implement Hmac verification on incoming requests but forget to apply per-request authorization on the data returned, leading to an excessive data exposure finding in the scan. middleBrick detects this by comparing the authenticated (but unauthenticated-style) scan results against the expected data minimization principle, highlighting endpoints that return broader data than necessary. Remediation requires coupling Hmac-based integrity checks with strict response filtering, field-level permissions, and careful schema design that excludes sensitive fields unless explicitly required and authorized.
Hmac Signatures-Specific Remediation in Fastapi — concrete code fixes
To address Excessive Data Exposure when using Hmac Signatures in Fastapi, you must enforce data minimization and authorization on the response side, independent of request integrity checks. Below are concrete code examples that demonstrate a secure pattern combining Hmac verification with strict response filtering.
First, define a Pydantic model that includes only the fields the client is allowed to see. This ensures that even if the database query returns extra columns, the serialized output is limited.
from pydantic import BaseModel
from typing import Optional
class UserPublic(BaseModel):
id: int
username: str
email: str
# Do not include password_hash, is_admin, or internal fields
Next, implement Hmac validation as a dependency that verifies the signature of incoming requests. This example uses hashlib and a shared secret to validate a timestamped payload.
import hashlib
import time
from fastapi import Depends, HTTPException, status
from fastapi.security import HmacSignature
def verify_hmac_signature(
payload: dict,
signature: str,
secret: str = "your-secure-secret"
) -> bool:
timestamp = payload.get("timestamp")
if not timestamp or abs(time.time() - int(timestamp)) > 300:
return False
message = f"{payload.get('user_id')}{timestamp}"
expected = hashlib.sha256((message + secret).encode()).hexdigest()
return signature == expected
Then, create an endpoint that uses the Hmac dependency for integrity and returns a filtered response using the authorized model.
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from .models import get_db, User as UserModel
from .schemas import UserPublic
router = APIRouter()
@router.get("/users/{user_id}", response_model=UserPublic)
def get_user(
user_id: int,
signature: str,
db: Session = Depends(get_db),
):
payload = {"user_id": user_id, "timestamp": int(time.time())}
if not verify_hmac_signature(payload, signature, secret="your-secure-secret"):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid or expired signature"
)
user_record = db.query(UserModel).filter(UserModel.id == user_id).first()
if not user_record:
raise HTTPException(status_code=404, detail="User not found")
# Map to public schema to avoid exposing sensitive fields
return UserPublic.from_orm(user_record)
For endpoints that return lists or nested resources, apply scope-based filtering and avoid serializing sensitive attributes. You can also integrate role checks before constructing the response model.
from typing import List
from fastapi import Security
class UserAdmin(UserPublic):
is_admin: bool
# Still exclude password_hash even for admin roles
@router.get("/users", response_model=List[UserPublic])
def list_users(
current_user: UserPublic = Security(get_current_user),
db: Session = Depends(get_db),
):
query = db.query(UserModel)
if not current_user.is_admin:
query = query.filter(UserModel.is_admin == False)
users = query.all()
return [UserPublic.from_orm(u) for u in users]
These patterns ensure that Hmac Signatures are used strictly for request integrity while response data exposure is controlled by explicit schemas, row-level filters, and field selection. middleBrick’s scans will highlight any endpoints that return broader data than the defined minimal models, helping you align implementation with the principle of least privilege.
Related CWEs: propertyAuthorization
| CWE ID | Name | Severity |
|---|---|---|
| CWE-915 | Mass Assignment | HIGH |