Skip to content
SEO Optimizer is live, Audit on page SEO and AI-search readiness. Try it free
Featured image for "GraphQL Introspection and Exposed API Docs in Production"
Security

GraphQL Introspection and Exposed API Docs in Production

·5 min read

GraphQL introspection lets a client ask a GraphQL API to describe itself: every query, mutation, type and field it supports. Developers rely on it for autocomplete and documentation. Left on in production for anonymous users, GraphQL introspection hands the same map to anyone probing your API. Public Swagger UI pages and OpenAPI files do the same for REST APIs. None of these is a vulnerability on its own, but each one makes finding the real vulnerabilities much faster.

What GraphQL Introspection Is

The GraphQL specification includes special fields such as __schema and __type. A single query against them returns the whole schema:

introspection.graphqlA minimal GraphQL introspection query
query {
  __schema {
    queryType { name }
    mutationType { name }
    types { name fields { name } }
  }
}

Tools like GraphiQL, Apollo Sandbox and code generators send a fuller version of this query automatically. If the server answers it for an anonymous request, anyone can run the same query with a single curl command.

Why GraphQL Introspection Matters for Security

  • It reveals hidden operations. Admin mutations, internal fields, deprecated queries and debug resolvers show up even if your front end never calls them.
  • It speeds up finding authorization bugs. The most common GraphQL problems are resolvers that forget to check who is asking. With the schema, an attacker can test every field one by one. See API security basics for broken object level authorization.
  • It shows sensitive field names, such as passwordHash, ssn or internalNotes, that tell an attacker where to look.
  • It helps build expensive queries. Knowing how types nest makes it easy to write deeply nested queries that overload the server.

Disabling GraphQL introspection is defense in depth. It does not fix a missing authorization check, and a determined attacker can still guess field names from error messages (some servers suggest "Did you mean..." fields). Treat it as one layer, not the fix.

When It Is Fine to Leave Introspection On

  • Public APIs that you document for outside developers, such as a platform API. The schema is public by design. Focus on authorization and rate limits instead.
  • Development and staging environments that are not reachable from the internet.
  • Authenticated introspection, where only signed-in staff or allowed clients can run it.

How to Disable GraphQL Introspection in Production

server.tsApollo Server: introspection only outside production
import { ApolloServer } from "@apollo/server";

const server = new ApolloServer({
  typeDefs,
  resolvers,
  introspection: process.env.NODE_ENV !== "production",
});
yoga.tsGraphQL Yoga: block introspection with an Envelop plugin
import { createYoga } from "graphql-yoga";
import { useDisableIntrospection } from "@graphql-yoga/plugin-disable-introspection";

const yoga = createYoga({
  schema,
  plugins: [useDisableIntrospection()],
});

Other servers have similar settings: graphql-java, Hot Chocolate, Strawberry and Hasura all let you turn introspection off or limit it to certain roles. Also turn off the in-browser IDE (GraphiQL, Playground, Apollo Sandbox landing page) on production endpoints, and add query depth and cost limits so a single request cannot ask for the whole database.

Exposed Swagger UI and OpenAPI Files

REST APIs have the same issue in a different form. Frameworks often publish /swagger-ui.html, /api-docs, /openapi.json or /v3/api-docs by default. That page lists every endpoint, parameter and model, and often lets visitors send requests straight from the browser.

  • If the API is public and documented, keep the docs, but host them where you choose and make sure they do not include internal or admin endpoints.
  • If the API is internal, turn the docs off in production or put them behind authentication. In Spring Boot that means the springdoc settings, in FastAPI the docs_url and openapi_url options, in NestJS not calling SwaggerModule.setup in production.

How to Check Your Site

A security scan looks for both problems. It sends an introspection query to common GraphQL paths such as /graphql, /api/graphql and /gql and reports "GraphQL introspection is enabled" only when the response actually contains the schema. It also detects GraphQL IDEs left on public endpoints, and checks dozens of common Swagger, OpenAPI and ReDoc paths, reporting a finding only when the response really is API documentation. The finding includes the exact path and the setting to change. It cannot see APIs on other domains or unusual paths, so check those yourself.

A Short GraphQL Introspection Checklist

  1. Decide whether your schema is meant to be public.
  2. If not, disable GraphQL introspection for anonymous users in production.
  3. Turn off GraphiQL or Playground on production endpoints.
  4. Add authorization checks in every resolver, not just at the gateway.
  5. Limit query depth, cost and rate.
  6. Hide or protect Swagger and OpenAPI docs for internal APIs.
  7. Keep CORS strict on API endpoints. See CORS explained.
FAQ

Perguntas frequentes

GraphQL introspection is a built-in feature that lets a client query the API's schema, including every type, field, query and mutation. Developer tools use it for autocomplete and documentation.

For private APIs, yes, at least for anonymous users. For public, documented APIs the schema is meant to be public, so focus on authorization, rate limits and query cost limits instead.

Not on its own. It exposes information that makes it faster to find real vulnerabilities, such as resolvers with missing authorization. Disabling it is defense in depth.

Set introspection: false in the ApolloServer options, or tie it to the environment, for example introspection: process.env.NODE_ENV !== 'production'.

For internal APIs, yes, because it lists every endpoint and parameter and often lets visitors send requests. Turn it off in production or require authentication. For public APIs, keep docs but exclude internal endpoints.

Find out which headers you're missing

Run a free security scan and get a plain-English breakdown of every header, cert, and exposed secret.

Run a free security scan