GraphQL introspection exposes your complete API schema — every type, field, mutation, and query — to anyone who can reach the endpoint. OWASP API Security Top 10 2023 API8 (Security Misconfiguration) and CWE-200 (Exposure of Sensitive Information) both flag introspection as an information disclosure risk. Attackers use introspection to map internal data models, identify admin mutations, discover deprecated endpoints, and understand field naming conventions before crafting targeted queries. In a production API, the schema is sensitive internal documentation. Development environments may leave introspection on by default; that default should be explicitly disabled when deploying to production.
Low because introspection is an information disclosure risk, not a direct exploitation path — but it systematically reduces the effort required to find and exploit other vulnerabilities.
Disable introspection in production by gating it on NODE_ENV. If schema exploration is needed for internal teams, restrict it behind authentication rather than removing it entirely.
// Apollo Server v4
import { ApolloServer } from '@apollo/server'
const server = new ApolloServer({
schema,
introspection: process.env.NODE_ENV !== 'production',
// Also disable the Explorer landing page in production
plugins: process.env.NODE_ENV === 'production'
? [ApolloServerPluginLandingPageDisabled()]
: [ApolloServerPluginLandingPageLocalDefault()]
})
For authenticated introspection, add a validation rule that checks context.user?.role === 'admin' before permitting __schema queries.
ID: api-security.abuse-prevention.graphql-introspection
Severity: low
What to look for: Enumerate every relevant item. If the application uses GraphQL, check whether introspection queries are allowed. Introspection exposes the entire API schema, which can aid attackers in finding vulnerabilities.
Pass criteria: At least 1 of the following conditions is met. GraphQL introspection is disabled in production or restricted to authenticated admin users. Introspection queries return an error in production.
Fail criteria: GraphQL introspection is enabled in production, allowing anyone to query the full schema.
Skip (N/A) when: The application does not use GraphQL.
Detail on fail: "GraphQL introspection enabled in production — schema is fully exposed to attackers"
Remediation: Disable introspection in production:
import { graphqlHTTP } from 'express-graphql'
app.use('/graphql', graphqlHTTP({
schema,
graphiql: process.env.NODE_ENV === 'development',
customFormatErrorFn: (error) => {
// Hide internal errors in production
if (process.env.NODE_ENV === 'production') {
return { message: 'Internal server error' }
}
return error
}
}))
// Or using Apollo Server
const server = new ApolloServer({
schema,
introspection: process.env.NODE_ENV === 'development',
debug: process.env.NODE_ENV === 'development'
})