← All news
graphql4 min read

GraphQL introspection left enabled in production is a security risk

By Seaworthy · June 21, 2026

Performance analytics graphs displayed on a laptop screen

Photo by Luke Chesser on Unsplash

GraphQL ships with a feature called introspection: ask the API what it can do, and it will tell you. Every type, every field, every query and mutation, laid out in a machine-readable schema. It is invaluable during development. In production, it is handing attackers a map of your API.

This is not a theoretical risk. It is the starting point for most GraphQL-targeted attacks, and it is trivially easy to check.

What introspection actually exposes

When introspection is enabled, anyone can send this query and get back a complete description of your entire API surface:

{
  __schema {
    types {
      name
      fields {
        name
        type {
          name
          kind
        }
      }
    }
  }
}

The response is not just "yes, there's a user type." It returns every field on every type, including internal admin types, soft-deleted fields you forgot to remove, and anything you assumed was hidden because it wasn't in your public docs.

Field names are often revealing. adminBypassToken, internalAuditLog, debugUserId, legacyPaymentMethod — these names exist because developers are communicating intent to each other. Introspection makes that communication visible to everyone on the internet.

Why AI-generated APIs are especially exposed

AI-generated GraphQL schemas tend to be verbose. The model doesn't know what to leave out, so it includes everything. Internal status fields, admin mutation hooks, debug queries, all of it ends up in the schema because it seemed useful while generating.

When a human writes an API by hand, there's natural friction. You think about whether a field should exist. AI generation removes that friction, which is mostly good, but it means your schema can accumulate surface area you didn't consciously choose.

Introspection in production means every one of those fields is documented and discoverable.

Checking if you're exposed

The quickest test is a direct query against your endpoint:

curl -X POST https://your-api.com/graphql \
  -H "Content-Type: application/json" \
  -d '{"query":"{ __schema { queryType { name } } }"}'

If you get a response with queryType data instead of an error, introspection is on. That's your answer. Tools like GraphQL Voyager will take that introspection response and render a full visual map of your schema. Attackers use exactly this workflow.

How to disable it

The right fix depends on your stack. In Apollo Server (Node.js), it's a single configuration option:

const server = new ApolloServer({
  typeDefs,
  resolvers,
  introspection: process.env.NODE_ENV !== 'production',
});

Note: Apollo Server 4 disables introspection automatically when NODE_ENV is set to production. If you're on an older version or a different framework, you need to handle this yourself.

For Python with graphene-django, the recommended approach is to add graphene_django.views.GraphQLView with graphiql=False and apply a middleware that rejects introspection queries. For Go with gqlgen, you control this at the transport registration level rather than a boolean flag — simply don't register the introspection handler on your production server setup.

If your framework doesn't offer a built-in toggle, a middleware layer that rejects any query containing __schema or __type will cover you.

The "but it's behind auth" objection

Some teams leave introspection on and argue that their API requires authentication, so only authorized users can query it. This is a weak position.

It assumes your authentication is perfect and that no token will ever leak. It exposes your schema to every authenticated user, including customers who shouldn't know your internal field names. And once a token is compromised (tokens do get compromised), the attacker has a complete blueprint of what to target.

Disabling introspection does not make a bad API secure. But it removes information that makes a bad API easier to exploit. That trade-off is worth making.

What about development tooling?

This is a fair concern. GraphQL Playground, Apollo Studio, and most schema exploration tools rely on introspection to work. The answer is environment-specific configuration: on in development, off in production.

If you need schema exploration in a staging or production-adjacent environment, serve the SDL file separately with proper access controls rather than leaving introspection open to the public internet. A schema registry is the right long-term solution here.


Seaworthy flags exposed GraphQL introspection endpoints as part of its configuration checks, covering this and other production API misconfigurations that commonly appear in AI-assisted codebases.

This article was generated by AI and summarises publicly available sources.

From the makers of Seaworthy

Seaworthy scans your repo for the issues covered in articles like this one.

Security gaps, exposed secrets, and misconfigurations — caught before you deploy. Free to run, no account needed.

$ npx seaworthycode