Data Exposure in Fastapi with Hmac Signatures
Data Exposure in Fastapi with Hmac Signatures — how this specific combination creates or exposes the vulnerability
Data exposure in FastAPI applications that use HMAC signatures can occur when integrity checks are applied only to a subset of request data or when signatures are computed over representations that inadvertently include sensitive information. HMAC is designed to verify that a message has not been altered, but it does not encrypt payloads. If you compute the HMAC over a JSON body that contains PII, secrets, or internal identifiers and then transmit the raw body alongside the signature, the data remains visible to anyone who can observe the request.
In FastAPI, a common pattern is to read the raw request body, compute an HMAC with a shared secret, and compare it to a header such as X-API-Signature. Because FastAPI may parse the body into models for you, developers sometimes mistakenly rely on parsed models for signing while still logging or exposing the raw or parsed data in error messages, audit logs, or stack traces. This creates a data exposure path: an attacker who can inject or observe logs might capture sensitive fields that were included in the hashed payload or in application telemetry. MiddleBrick scans detect scenarios where endpoints accept highly privileged or sensitive fields (such as role=admin, permissions, or internal IDs) without additional authorization checks, even when an HMAC is present.
Another subtle risk arises from inconsistent signature scope. For example, including a timestamp or nonce in the HMAC prevents replay, but if the timestamp is also reflected in response metadata or debug output, it may contribute to correlation or inference attacks. Similarly, if the HMAC covers only selected headers or a subset of query parameters while the rest of the request influences sensitive behavior, an attacker might infer relationships between signed and unsigned data. MiddleBrick’s checks for BOLA/IDOR and Property Authorization are designed to uncover cases where object-level permissions are missing, which can combine with HMAC usage to amplify data exposure by allowing one user to reference another user’s resources despite valid signature checks.
Consider an endpoint that accepts a JSON payload and an X-API-Signature header. If the application computes the HMAC over the entire JSON string but then deserializes the JSON into a Pydantic model that logs the model’s __dict__ for debugging, sensitive fields such as email or internal IDs may be written to logs. Even though the signature ensures integrity, the data is exposed through logging. Similarly, returning a full resource representation that includes fields the client should not see—such as password hashes or internal state—constitutes data exposure independent of signature validity.
To assess this with an unauthenticated scan, MiddleBrick tests whether endpoints reflect sensitive input values in responses, error messages, or documentation and whether authorization checks are applied to object-level identifiers. The tool examines the OpenAPI spec to see which parameters and headers are included in the signature scope and cross-references runtime behavior to identify mismatches. By correlating findings from the Authentication, BOLA/IDOR, and Data Exposure checks, it highlights combinations where HMAC signatures exist but do not sufficiently protect sensitive data from being read or inferred.
Hmac Signatures-Specific Remediation in Fastapi — concrete code fixes
Remediation focuses on minimizing the data included in the HMAC scope, ensuring that sensitive fields are excluded from hashed representations, and avoiding exposure of payloads in logs or responses. You should compute the HMAC only over the parts of the request that are necessary for integrity (typically selected headers and a canonical JSON string that excludes sensitive fields), and you should avoid logging raw or parsed sensitive data.
Below is a concrete FastAPI example that shows how to compute and verify an HMAC over a filtered payload. The example excludes sensitive fields before hashing and uses a constant-time comparison to avoid timing attacks.
import json
import hmac
import hashlib
from typing import Any, Dict
from fastapi import FastAPI, Request, HTTPException, Header
from pydantic import BaseModel
app = FastAPI()
SECRET = b"super-secret-shared-key" # store in secure configuration/secrets manager
# Model for incoming data, excluding highly sensitive fields from signing/sanitization
class Command(BaseModel):
action: str
target: str
# sensitive fields can still be present but should be omitted from the HMAC input
_internal: Dict[str, Any] = {}
def filter_sensitive(data: Dict[str, Any]) -> Dict[str, Any]:
# Remove fields that should not influence the signature
return {k: v for k, v in data.items() if k not in ("password", "token", "internal_id")}
def compute_hmac(payload_bytes: bytes) -> str:
return hmac.new(SECRET, payload_bytes, hashlib.sha256).hexdigest()
@app.post("/command")
async def execute_command(request: Request, x_api_signature: str = Header(...)):
raw_body = await request.body()
# Parse for business logic but do not rely on parsed data for signature verification input
try:
parsed = json.loads(raw_body)
except json.JSONDecodeError:
raise HTTPException(status_code=400, detail="Invalid JSON")
# Compute HMAC over filtered canonical JSON to avoid exposing sensitive fields
filtered = filter_sensitive(parsed)
canonical = json.dumps(filtered, separators=(",", ":"), sort_keys=True).encode("utf-8")
expected = compute_hmac(canonical)
if not hmac.compare_digest(expected, x_api_signature):
raise HTTPException(status_code=401, detail="Invalid signature")
# Use parsed data for business logic, but avoid logging raw_body or parsed sensitive fields
return {"status": "accepted", "action": filtered.get("action"), "target": filtered.get("target")}
This approach ensures that the HMAC covers only the data required for integrity, excluding passwords, tokens, or internal IDs. It also avoids logging the raw body after validation, reducing the risk of data exposure through application telemetry.
Additionally, you should enforce object-level authorization (BOLA/IDOR) checks so that even a valid signature does not permit access to resources that belong to other subjects. Combine this with output filtering to ensure responses do not include sensitive fields. MiddleBrick’s Pro plan continuous monitoring can help you detect configurations where signatures are present but object-level permissions or output sanitization are missing, which is especially important when handling tokens, roles, or internal identifiers.
For automation and CI/CD integration, the middleBrick CLI allows you to scan endpoints from the terminal and fail builds if risk thresholds are exceeded. Use middlebrick scan <url> to validate your endpoints regularly, and consider the GitHub Action to gate merges when the Data Exposure score declines. These integrations complement runtime fixes by ensuring that regressions are caught before deployment.
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 |