HIGH graphql introspectionfastapiapi keys

Graphql Introspection in Fastapi with Api Keys

Graphql Introspection in Fastapi with Api Keys — how this specific combination creates or exposes the vulnerability

GraphQL introspection is a feature that allows clients to query the schema of a GraphQL service, including types, queries, and mutations. In FastAPI, when GraphQL endpoints are exposed without restricting introspection, any unauthenticated or poorly authenticated client can retrieve the full schema. This behavior becomes a security risk when API keys are used for authentication but are not properly validated before the introspection query reaches the GraphQL layer.

When API keys are accepted but not rigorously enforced across all operations, introspection can remain enabled for keyed requests. An attacker who discovers or guesses a valid API key can issue an introspection query to map the API surface, revealing sensitive types, queries, and potential entry points for further attacks such as BOLA or IDOR. Even if the API key is intended to limit access to certain resources, introspection can expose fields and relationships that should be hidden, effectively bypassing intended visibility controls.

In FastAPI, this often occurs when GraphQL routes are mounted without a pre-execution check that blocks introspection based on authentication context. The API key may validate identity, but if the GraphQL resolver or schema introspection is not explicitly disabled for keyed requests, the endpoint remains informative to an attacker. This is especially relevant in unauthenticated attack surface testing, where middleBrick runs checks such as Authentication and BOLA/IDOR in parallel, detecting whether introspection is allowed alongside key-based access controls.

Real-world examples include schemas exposing internal data models like User, Account, or Payment, which can hint at internal architecture or data storage patterns. If introspection is allowed, attackers can combine schema knowledge with automated probing to craft targeted queries, increasing the effectiveness of other checks such as Property Authorization and Input Validation.

middleBrick identifies this risk by testing the unauthenticated attack surface and correlating findings with authentication mechanisms. Reports highlight whether introspection is permitted alongside API key validation, providing severity-ranked findings and remediation guidance mapped to frameworks such as OWASP API Top 10 and SOC2 controls.

Api Keys-Specific Remediation in Fastapi — concrete code fixes

To secure GraphQL introspection in FastAPI when using API keys, you must explicitly disable introspection for requests that include API key authentication or restrict introspection based on key validity and scope. Below are concrete code examples demonstrating how to implement this.

Example 1: Disable introspection for all keyed requests

Use a custom introspection_resolver that returns None when an API key is present, effectively disabling introspection for authenticated or keyed clients.

from fastapi import FastAPI, Depends, HTTPException, Security
from starlette.graphql import GraphQLRoute
from graphene import ObjectType, String, Schema
from starlette.requests import Request

app = FastAPI()

class Query(ObjectType):
    hello = String(name=String(default_value="world"))

    def resolve_hello(self, info, name):
        return f"Hello {name}"

# Dependency that extracts and validates API key
def get_api_key(request: Request):
    api_key = request.headers.get("X-API-Key")
    if not api_key or api_key != "your-secure-key":
        raise HTTPException(status_code=403, detail="Invalid or missing API key")
    return api_key

# Disable introspection when API key is used
introspection_resolver = lambda *_: None

schema = Schema(query=Query, introspection=introspection_resolver)

@app.route("/graphql", methods=["POST", "GET"])
def graphql_endpoint(request: Request, api_key: str = Security(get_api_key)):
    from starlette.graphql import run_graphql_request
    return run_graphql_request(
        request=request,
        schema=schema,
        debug=True,
    )

Example 2: Conditionally allow introspection based on key scope

Allow introspection only for a special key or role, ensuring that production keys do not expose schema details.

from fastapi import FastAPI, Security, HTTPException
from starlette.graphql import GraphQLRoute
from graphene import ObjectType, String, Schema
from starlette.requests import Request

app = FastAPI()

class Query(ObjectType):
    public_data = String()

    def resolve_public_data(self, info):
        return "public"

ALLOW_INTROSPECTION_KEYS = {"debug-key-123"}

def get_api_key(request: Request):
    key = request.headers.get("X-API-Key")
    if not key:
        raise HTTPException(status_code=403, detail="API key required")
    return key

# Custom resolver that checks key permissions
def safe_introspection_resolver(root, info):
    api_key = info.context.headers.get("X-API-Key", "")
    if api_key in ALLOW_INTROSPECTION_KEYS:
        return None  # Allow introspection
    return None  # Always disable introspection for safety; adjust as needed

schema = Schema(query=Query, introspection=safe_introspection_resolver)

@app.get("/graphql")
def graphql(request: Request, api_key: str = Security(get_api_key)):
    from starlette.graphql import run_graphql_request
    return run_graphql_request(request=request, schema=schema, debug=True)

General remediation practices

  • Ensure introspection is disabled by default in production builds, regardless of authentication.
  • Validate API keys before allowing any GraphQL execution, and treat keys as credentials.
  • Combine these measures with checks for BOLA/IDOR and Rate Limiting to reduce the attack surface.
  • Use middleware or route dependencies to enforce key presence and correctness before the request reaches the GraphQL layer.

These fixes align with guidance provided by tools like middleBrick, which can detect whether introspection is exposed alongside API key usage and provide prioritized remediation steps.

Related CWEs: dataExposure

CWE IDNameSeverity
CWE-200Exposure of Sensitive Information HIGH
CWE-209Error Information Disclosure MEDIUM
CWE-213Exposure of Sensitive Information Due to Incompatible Policies HIGH
CWE-215Insertion of Sensitive Information Into Debugging Code MEDIUM
CWE-312Cleartext Storage of Sensitive Information HIGH
CWE-359Exposure of Private Personal Information (PII) HIGH
CWE-522Insufficiently Protected Credentials CRITICAL
CWE-532Insertion of Sensitive Information into Log File MEDIUM
CWE-538Insertion of Sensitive Information into Externally-Accessible File HIGH
CWE-540Inclusion of Sensitive Information in Source Code HIGH

Frequently Asked Questions

Can API keys alone prevent GraphQL introspection attacks?
No. API keys validate identity but do not disable introspection by default. Explicitly disable or restrict introspection in your GraphQL schema configuration to prevent schema exposure.
How does middleBrick detect GraphQL introspection risks with API keys?
middleBrick tests the unauthenticated attack surface and checks whether introspection queries are permitted when API key headers are present, correlating authentication mechanisms with schema exposure findings.