GraphQL Introspection Query Enabled
Description
GraphQL introspection is a built-in feature that allows clients to query a GraphQL server's complete schema, including all types, fields, queries, mutations, and their relationships. While valuable during development for generating documentation and building tools, leaving introspection enabled in production environments exposes your API's entire structure to potential attackers.
This information disclosure allows malicious actors to map your API's attack surface, identify sensitive operations, discover hidden or deprecated endpoints, and craft targeted attacks against specific fields or mutations. Introspection queries can be executed by any client without authentication, making this a low-barrier reconnaissance technique.
Production GraphQL APIs should disable introspection to follow the security principle of least privilege, ensuring that only authorized developers and systems have access to schema information.
Remediation
Disable GraphQL introspection in all production environments by implementing server-side validation rules that reject introspection queries. The specific implementation varies by GraphQL server framework:
Apollo Server (Node.js):
const { ApolloServer } = require('apollo-server');
const { NoIntrospection } = require('graphql-disable-introspection');
const server = new ApolloServer({
typeDefs,
resolvers,
introspection: process.env.NODE_ENV !== 'production',
validationRules: [
process.env.NODE_ENV === 'production' ? NoIntrospection : null
].filter(Boolean)
});
Express-GraphQL (Node.js):
const { graphqlHTTP } = require('express-graphql');
const { NoIntrospection } = require('graphql-disable-introspection');
app.use('/graphql', graphqlHTTP({
schema: schema,
graphiql: process.env.NODE_ENV !== 'production',
validationRules: [
process.env.NODE_ENV === 'production' ? NoIntrospection : null
].filter(Boolean)
}));
GraphQL Yoga (Node.js):
import { createYoga } from 'graphql-yoga';
import { useDisableIntrospection } from '@graphql-yoga/plugin-disable-introspection';
const yoga = createYoga({
schema,
plugins: [
process.env.NODE_ENV === 'production' ? useDisableIntrospection() : null
].filter(Boolean)
});
Django Graphene (Python):
from graphene_django.views import GraphQLView
from graphql import validate
from graphql.validation import NoSchemaIntrospectionCustomRule
import os
class ProductionGraphQLView(GraphQLView):
def execute_graphql_request(self, *args, **kwargs):
if os.environ.get('DJANGO_ENV') == 'production':
kwargs['validation_rules'] = (
validate.specified_rules + [NoSchemaIntrospectionCustomRule]
)
return super().execute_graphql_request(*args, **kwargs)
# In urls.py
urlpatterns = [
path('graphql/', ProductionGraphQLView.as_view(graphiql=False)),
]
Additional Best Practices:
• Use environment variables to control introspection based on deployment environment
• Implement API authentication and authorization regardless of introspection settings
• Monitor GraphQL queries for introspection attempts in production logs
• Consider implementing rate limiting to prevent schema enumeration attempts
• Maintain internal documentation of your GraphQL schema for authorized developers