HIGH graphql introspectiondjangobasic auth

Graphql Introspection in Django with Basic Auth

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

GraphQL introspection allows clients to query the schema for types, queries, and mutations. When a Django GraphQL endpoint is exposed with Basic Authentication but introspection is not explicitly disabled, unauthenticated or partially authenticated attackers can use introspection queries to map the API surface. middleBrick’s Authentication and BOLA/IDOR checks flag this as a risk because the presence of Basic Auth does not inherently limit introspection if views or GraphQL routers do not enforce stricter controls.

In Django, GraphQL is commonly served via packages such as graphene-django or Strawberry. If the GraphQL view is mounted at a path like /graphql/ and Basic Auth is applied at the web server (e.g., via HTTPBasicAuth in Apache/Nginx) or at the Django view level, an attacker with network access or partial credentials may still send an introspection query. Successful introspection reveals which types, queries, and mutations exist, which in turn aids in crafting further attacks such as IDOR or BFLA. middleBrick’s GraphQL-related checks correlate introspection exposure with authentication mechanisms and flag scenarios where introspection is reachable under Basic Auth without additional schema-level restrictions.

Consider a typical Django GraphQL view using graphene:

from django.http import HttpRequest
from graphene_django.views import GraphQLView
class BasicAuthGraphQLView(GraphQLView):
    def get_response(self, request: HttpRequest, data):
        # Weak: only checks a static token, not per-user credentials
        auth = request.META.get('HTTP_AUTHORIZATION', '')
        if not auth.startswith('Basic '):
            return {'errors': [{'message': 'Unauthorized'}]}
        return super().get_response(request, data)

If this view is deployed without schema-level introspection disabling, an attacker can POST an introspection query to the endpoint and enumerate the schema even when Basic Auth is present but not tied to a restrictive permission model. middleBrick’s Property Authorization and Input Validation checks help identify whether introspection is guarded by proper authorization logic.

Additionally, when using Django with an OpenAPI/Swagger spec that describes a GraphQL endpoint, the spec may inadvertently document the GraphQL route as a standard HTTP endpoint. middleBrick’s OpenAPI/Swagger analysis resolves $ref paths and cross-references runtime findings, highlighting mismatches where introspection is reachable despite documented authentication requirements.

Basic Auth-Specific Remediation in Django — concrete code fixes

To secure a GraphQL endpoint in Django when using Basic Authentication, you should combine transport-level authentication with schema-level controls. Disable introspection in production and ensure that any Basic Auth wrapper validates credentials properly and does not rely on static tokens or missing checks.

1) Disable GraphQL introspection in production builds. With graphene-django, set graphql_schema with introspection disabled:

from graphene import Schema
from graphene_django.models import DjangoObjectType
from django.conf import settings
schema = Schema(
    query=MyQuery,
    mutation=MyMutation,
    enable_introspection=settings.DEBUG  # False in production
)

With Strawberry, use strawberry.Schema and omit the enable_introspection flag or explicitly set it to False in production:

import strawberry
from django.conf import settings
@strawberry.type
class Query:
    hello: str = "world"
schema = strawberry.Schema(
    query=Query,
    enable_introspection=settings.DEBUG
)

2) Implement robust Basic Auth at the view or middleware level, validating credentials per request rather than using a static token. Example using Django REST Framework’s HTTPBasicAuthentication combined with a custom permission:

from rest_framework.authentication import HTTPBasicAuthentication
from rest_framework.permissions import BasePermission, SAFE_METHODS
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
class HasValidBasicAuth(BasePermission):
    def has_permission(self, request, view):
        auth = request.META.get('HTTP_AUTHORIZATION', '')
        if not auth.startswith('Basic '):
            return False
        # Validate credentials against Django user model or a secret store
        # Example: decode and check against environment variables
        import base64
        encoded = auth.split(' ')[1]
        decoded = base64.b64decode(encoded).decode('utf-8')
        username, password = decoded.split(':', 1)
        # Replace with secure credential check (e.g., secrets manager or Django user)
        valid = (username == 'apiuser' and password == 'strongpassword')
        return valid
class SecureGraphQLView(APIView):
    authentication_classes = [HTTPBasicAuthentication]
    permission_classes = [HasValidBasicAuth]
    def post(self, request):
        # Your GraphQL handling logic here
        return Response({'data': 'ok'})

3) If you rely on web server Basic Auth (e.g., Nginx), ensure the GraphQL path is not unintentionally exposed. Use location-level restrictions and validate that introspection is disabled at the application level, as server-level auth may still allow introspection if misconfigured.

middleBrick’s CLI can be used in scripts to verify that introspection is disabled and that authentication is required: middlebrick scan <url>. The GitHub Action can enforce a security score threshold to prevent insecure configurations from reaching production, while the MCP Server allows you to scan APIs directly from your AI coding assistant during development.

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 disabling introspection break existing GraphQL clients?
Yes, clients that rely on introspection for tooling or dynamic queries will stop working. Disable introspection in production and provide schema documentation or a controlled alternative for developers.
Is Basic Auth sufficient for protecting a GraphQL endpoint in production?
Basic Auth alone is not sufficient. Always combine it with HTTPS, per-request credential validation, and schema-level controls such as disabling introspection and enforcing proper permissions.