Graphql Introspection in Fastapi with Hmac Signatures
Graphql Introspection in Fastapi with Hmac Signatures — how this specific combination creates or exposes the vulnerability
GraphQL introspection in a FastAPI service that uses HMAC signatures can expose the API surface even when authentication is enforced, because introspection queries are typically processed before signature validation is applied to the operation. An attacker can send a standard introspection request to the GraphQL endpoint and learn the full schema, including types, queries, and mutations, which may reveal sensitive business logic or hidden endpoints.
When HMAC signatures are implemented as a middleware or header check, they often validate the request after the GraphQL resolver pipeline has already begun. If introspection is allowed for unauthenticated or partially authenticated requests, the detailed schema returned can aid in crafting further attacks, such as IDOR or BOLA, by exposing query patterns and required fields. The combination therefore creates a risk where the very mechanism intended to verify request integrity (HMAC) does not restrict the introspection feature, allowing information leakage that would otherwise be protected.
In FastAPI, if the GraphQL route is defined without early rejection of introspection for unverified requests, the response includes type definitions and query relationships. This can be particularly dangerous when the API is exposed to unauthenticated scanning tools, because introspection can be run at any time to map the attack surface. HMAC signatures that only verify integrity of known operations do not inherently block introspection unless explicitly enforced at the route or schema level.
To illustrate, consider a FastAPI route that accepts POST JSON with a signature header but does not validate the presence or correctness of the signature before invoking the GraphQL handler. An attacker can send:
POST /graphql
Content-Type: application/json
{ "query": "{ __schema { queryType { name } } }"}
and receive a full schema in response if introspection is permitted. The HMAC signature, if checked later, does not prevent this disclosure. This highlights the need to treat introspection as a privileged operation and align it with the security assumptions behind HMAC verification.
Hmac Signatures-Specific Remediation in Fastapi — concrete code fixes
To secure GraphQL introspection alongside HMAC signatures in FastAPI, enforce signature validation before the GraphQL resolver runs and explicitly disable introspection for requests that cannot be verified. Below are concrete code examples showing how to implement HMAC verification and restrict introspection in a FastAPI application.
First, implement an HMAC verification dependency that checks a shared secret and a timestamp to prevent replay attacks:
import hmac
import hashlib
import time
from fastapi import Depends, HTTPException, Header, FastAPI
from pydantic import BaseModel
from typing import Optional
SECRET_KEY = b"your-secure-secret"
TIME_TOLERANCE = 30 # seconds
class GraphQLRequest(BaseModel):
query: str
variables: Optional[dict] = None
def verify_hmac(x_signature: str = Header(...), timestamp: str = Header(...)):
# Prevent replay attacks by checking timestamp
try:
ts = int(timestamp)
except ValueError:
raise HTTPException(status_code=400, detail="Invalid timestamp")
if abs(time.time() - ts) > TIME_TOLERANCE:
raise HTTPException(status_code=401, detail="Request expired")
body = GraphQLRequest # In practice, you would read the raw body carefully
# Note: In real usage, read raw request body for HMAC calculation
# This is a simplified example
signature = x_signature
computed = hmac.new(SECRET_KEY, msg=signature.encode(), digestmod=hashlib.sha256).hexdigest()
if not hmac.compare_digest(computed, signature):
raise HTTPException(status_code=401, detail="Invalid signature")
return True
Next, configure the GraphQL endpoint to require this dependency and disable introspection when verification is not applied. If you use a library such as strawberry or graphene with FastAPI, wrap the route so that introspection is only allowed when the HMAC check passes:
from fastapi import FastAPI, Depends
from starlette.responses import JSONResponse
app = FastAPI()
@app.post("/graphql")
async def graphql_endpoint(
data: GraphQLRequest,
_: bool = Depends(verify_hmac)
):
# Here, integrate with your GraphQL library
# For example, using a function that handles query execution
# Ensure that introspection queries are rejected when not explicitly allowed
if "__schema" in data.query or "__type" in data.query:
raise HTTPException(status_code=403, detail="Introspection is not allowed")
# Proceed with query execution
return JSONResponse({"data": {}})
Alternatively, if you allow introspection for authenticated or verified requests only, add logic to inspect the HMAC validity and the request context before permitting introspection. This ensures that schema exposure is gated behind the same integrity checks used for other operations.
Finally, consider rotating the HMAC secret periodically and storing it securely, such as in environment variables or a secrets manager. Combine this with rate limiting to reduce the impact of brute-force attempts against the signature validation. These steps reduce the exposure of GraphQL metadata while preserving the integrity guarantees provided by HMAC signatures.
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 |