Request Smuggling in Fastapi with Hmac Signatures
Request Smuggling in Fastapi with Hmac Signatures — how this specific combination creates or exposes the vulnerability
Request smuggling occurs when an attacker sends a request that is interpreted differently by a frontend proxy versus a backend application. In Fastapi, using Hmac Signatures for request authentication can inadvertently highlight or enable smuggling if the application does not enforce strict message boundary handling before signature verification.
When a Fastapi service relies solely on an Hmac Signature—typically passed in a header such as x-api-signature—to validate integrity, it may process the request body without first ensuring that the Content-Length or Transfer-Encoding headers are consistent with the actual message stream. If the application reads the body for business logic before verifying the Hmac, or if it uses a streaming body that allows multiple parsers, an attacker can craft a request that combines two requests in one connection (e.g., a small request followed by a larger one). A misconfigured proxy that uses different parsing rules may forward only the first request to Fastapi, while the backend consumes more bytes than expected, causing the second request to be processed in the wrong context or left unhandled.
Specifically, if the Hmac is computed over the raw bytes of the body, an attacker can send a request with a valid Hmac for a benign payload, then smuggle additional requests by manipulating chunked encoding or content-length mismatches. Fastapi, using Starlette under the hood, may expose the raw receive stream via request.body() or request.stream(). If the application consumes the stream to compute the Hmac and then later attempts to parse JSON or form data, the stream may already be partially consumed, leading to inconsistent parsing and potential injection of a second request into the next transaction. This is a request smuggling vector enabled by the interaction between Hmac-based validation and improper stream handling, not by the cryptographic strength of the Hmac itself.
Notably, middleBrick’s scans detect such issues under the BOLA/IDOR and Unsafe Consumption checks by analyzing how the endpoint processes raw streams and whether signature validation occurs after body consumption. The scanner also flags missing strict transport parsing that could allow ambiguous message boundaries, a common precursor to smuggling in API gateways that sit in front of Fastapi services.
Hmac Signatures-Specific Remediation in Fastapi — concrete code fixes
To mitigate request smuggling when using Hmac Signatures in Fastapi, ensure that the request body is read exactly once, validated for message boundaries before cryptographic verification, and never consumed for business logic before signature validation.
Below is a secure pattern that reads the raw body, verifies the Hmac, and then parses the payload only after integrity is confirmed. This avoids stream reuse and ensures the same bytes used for the signature are the bytes parsed by the application.
import hashlib
import hmac
from fastapi import FastAPI, Request, HTTPException, Header
from pydantic import BaseModel
import json
app = Fastapi()
SECRET_KEY = b"super-secret-key-change-in-prod"
class Payload(BaseModel):
user_id: int
action: str
def verify_hmac(raw_body: bytes, signature: str) -> bool:
computed = hmac.new(SECRET_KEY, raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(computed, signature)
@app.post("/secure-action")
async def secure_action(request: Request, x_api_signature: str = Header(...)):
# Read the body exactly once
raw_body = await request.body()
# Verify message integrity before any parsing
if not verify_hmac(raw_body, x_api_signature):
raise HTTPException(status_code=401, detail="Invalid signature")
# Only after verification, parse the payload
try:
payload = json.loads(raw_body)
data = Payload(**payload)
except (json.JSONDecodeError, ValueError):
raise HTTPException(status_code=400, detail="Invalid JSON")
# Business logic using validated data
return {"status": "ok", "user_id": data.user_id, "action": data.action}
Key points in this remediation:
await request.body()is called once and stored; no subsequent reads fromrequest.stream()occur.- Hmac verification happens before any deserialization, ensuring the bytes being verified are exactly the bytes parsed.
- The signature header is explicitly required; avoid optional signatures that could lead to inconsistent validation paths.
Additionally, deploy behind a properly configured reverse proxy or API gateway that normalizes Transfer-Encoding and Content-Length, and that does not allow ambiguous chunked encoding passthrough. middleBrick’s Pro plan supports continuous monitoring of such configurations, scanning APIs on a schedule and alerting if risky parsing patterns are detected in the OpenAPI spec or runtime behavior.
For CI/CD integration, use the middleBrick GitHub Action to fail builds if the scan detects unsafe body consumption or missing strict message boundary controls, preventing vulnerable deployments from reaching production.