HIGH graphql introspectionflaskbasic auth

Graphql Introspection in Flask with Basic Auth

Graphql Introspection in Flask with Basic Auth — how this specific combination creates or exposes the vulnerability

GraphQL introspection in a Flask application exposes the full schema, including types, queries, and mutations. When combined with HTTP Basic Auth, introspection remains available without additional access controls, because the GraphQL endpoint typically responds to introspection queries regardless of authentication state. This creates a risk where an unauthenticated or low-privilege attacker can map the API surface and discover sensitive fields, relationships, and operations that can be leveraged in further attacks.

Basic Auth transmits credentials in an encoded, not encrypted, form unless protected by TLS. If TLS is terminated correctly but access control is not enforced at the GraphQL resolver or schema level, an attacker can pair a captured Authorization header with introspection queries to enumerate the API. Common misconfigurations include allowing introspection in production, failing to disable it conditionally, or not coupling introspection permissions with the authentication layer. For example, a Flask route that passes all requests to a GraphQL view without validating scopes or roles may expose user data structures, mutation inputs, and internal object identifiers through introspection.

In a black-box scan, middleBrick tests GraphQL introspection by attempting to query the schema and cross-referencing findings with Basic Auth–protected endpoints. If introspection returns data alongside a 401 for unauthorized requests, the scan flags Authentication issues and highlights BOLA/IDOR risks when object-level authorization is missing. This combination increases the severity of findings because attackers can enumerate identifiers and then test direct object references. The scanner also checks whether input validation and rate limiting apply to introspection queries, as unrestricted introspection can amplify enumeration attacks.

Real-world attack patterns include using introspection to locate ID fields in queries, then crafting Insecure Direct Object Reference (IDOR) or BOLA attempts with captured credentials. For instance, if introspection reveals a user query like user(id: ID!): User, an attacker can iterate numeric IDs when weak authorization is present. OWASP API Top 10 A1 (Broken Object Level Authorization) and A7 (Rate Limiting Misconfiguration) map to these scenarios, and findings often align with PCI-DSS and SOC2 controls around access to sensitive data.

middleBrick detects these issues by running parallel checks against the unauthenticated surface and, when credentials are provided, testing authenticated paths. Reports include per-category breakdowns, prioritized findings with severity, and remediation guidance. In the Pro plan, continuous monitoring can rescan GraphQL endpoints on a schedule and alert on schema changes that reintroduce exposure.

Basic Auth-Specific Remediation in Flask — concrete code fixes

To secure GraphQL introspection in Flask with Basic Auth, enforce authentication before allowing introspection and ensure credentials are handled safely. Use HTTPS to protect the encoded credentials in transit, and apply strict access controls at the resolver or middleware layer.

Example: Conditional Introspection with Basic Auth

Disable introspection by default and enable it only for authenticated admin users. The following snippet shows a Flask app with Basic Auth and guarded introspection:

from flask import Flask, request, jsonify
import base64

app = Flask(__name__)

VALID_USERS = {
    "admin": "strongpassword123",
    "analyst": "readonlypass"
}

def check_auth(header_value):
    try:
        auth_type, encoded = header_value.split(" ", 1)
        if auth_type.lower() != "basic":
            return None
        decoded = base64.b64decode(encoded).decode("utf-8")
        username, password = decoded.split(":", 1)
        if username in VALID_USERS and VALID_USERS[username] == password:
            return username
    except Exception:
        return None
    return None

@app.before_request
def require_auth_for_graphql():
    if request.path == "/graphql":
        auth_header = request.headers.get("Authorization")
        user = check_auth(auth_header) if auth_header else None
        if user is None:
            return jsonify({"error": "Unauthorized"}), 401
        # Optionally attach user to request for resolvers
        request.user = user

@app.route("/graphql", methods=["POST"])
def graphql():
    from graphql import graphql_sync
    from my_schema import schema  # your constructed GraphQL schema
    data = request.get_json(force=True)
    query = data.get("query")
    # Example: block introspection for non-admin users
    if "__schema" in query and request.user != "admin":
        return jsonify({"error": "Introspection not allowed for your role"}), 403
    result = graphql_sync(schema, query)
    return jsonify(result.to_dict())

if __name__ == "__main__":
    app.run(ssl_context="adhoc")  # use proper TLS in production

In this pattern, check_auth validates Basic Auth credentials and returns the username or None. The before-request guard rejects unauthenticated requests to the GraphQL endpoint. Within the resolver, introspection queries are blocked for non-admin users, reducing exposure. For production, replace ssl_context="adhoc" with a proper certificate and store credentials securely, for example using environment variables or a secrets manager.

Alternative: Disabling Introspection Entirely

If introspection is not needed in production, disable it at the schema level. With graphql-core, set introspection=False when creating the GraphQL view:

from graphql import GraphQLSchema, build_schema
from graphql.server import GraphQLServer

schema_str = """
type Query {
    hello: String
}
"""
schema = build_schema(schema_str)

# In your Flask view, disable introspection
server = GraphQLServer(schema, introspection=False)

Disabling introspection prevents both authenticated and unauthenticated enumeration, which is the strongest mitigation. Combine this with rate limiting and monitoring to detect scanning attempts. The Pro plan’s continuous monitoring can verify that introspection remains disabled across deployments.

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

Does Basic Auth over HTTPS fully protect GraphQL introspection?
No. TLS protects credentials in transit, but if introspection is allowed without proper authorization checks, an authenticated or unauthenticated attacker can still enumerate the schema. Use per-request authentication checks and restrict introspection by role.
Can middleBrick detect GraphQL introspection issues when Basic Auth is used?
Yes. middleBrick tests both unauthenticated and authenticated flows when credentials are provided. It flags missing object-level authorization, excessive introspection exposure, and missing rate limits, with findings mapped to OWASP API Top 10 and compliance frameworks.