Safeguard
Application Security•

ASVS 5.0 V4.3.2: Disable GraphQL Introspection in Production

Introspection hands attackers your full schema. Turn it off in production unless the API is public by design, and test that suggestions do not leak it back.

Safeguard Security Team
3 min read

ASVS 5.0 V4.3.2 (level 2) requires that GraphQL introspection queries are disabled in production, unless the API is meant to be used by other parties.

Introspection is the built in feature that lets a client ask the server for its whole schema: every type, field, argument and mutation. Developer tools use it to power autocomplete and docs. An attacker uses it to get a free map of your API.

Why it matters

Introspection will not create vulnerabilities by itself. It makes finding them cheap. With the schema in hand, an attacker sees admin mutations, deprecated fields, internal types and odd arguments, and can aim authorization and injection tests at exactly the right places. Without it they have to guess.

Do not mistake this for access control. Hiding the schema does not replace authorization on every resolver. It removes a convenience for attackers and reduces noise, so it is a hardening step, not a fix.

How to implement it

Turn it off by environment. Apollo Server disables introspection by default when NODE_ENV is production, but set it explicitly so a config change cannot flip it silently:

import { ApolloServer } from '@apollo/server';
import { ApolloServerPluginLandingPageDisabled } from '@apollo/server/plugin/disabled';

const isProd = process.env.NODE_ENV === 'production';
const server = new ApolloServer({
  typeDefs,
  resolvers,
  introspection: !isProd,
  plugins: isProd ? [ApolloServerPluginLandingPageDisabled()] : [],
});

In other stacks, use the equivalent: a validation rule that rejects __schema and __type fields, such as the NoSchemaIntrospectionCustomRule that ships with graphql-js.

import { NoSchemaIntrospectionCustomRule } from 'graphql';
// pass in validationRules for production

Also turn off field suggestions ("Did you mean...") where your server supports it, because error messages can leak field names even when introspection is off. And remove GraphiQL or any playground from production builds.

How to test it

Send the standard introspection query to production.

curl -s https://api.example.com/graphql \
  -H 'content-type: application/json' \
  -d '{"query":"{ __schema { types { name } } }"}'

The response must be an error, not a schema. Next, send a misspelled field and read the error.

curl -s https://api.example.com/graphql -H 'content-type: application/json' \
  -d '{"query":"{ usr { id } }"}'

If the message says "Did you mean user?" your server still leaks field names. Disable suggestions. Run both checks in staging with production settings, and again after every deploy.

Common mistakes

  • Disabling introspection in code but leaving a playground or schema download route in place.
  • Forgetting a second GraphQL endpoint, such as an internal or versioned path.
  • Leaving field suggestions on, which lets attackers rebuild the schema by guessing.
  • Treating hidden schema as protection and skipping resolver level authorization.
  • Blocking introspection on an API that is meant for partners, and breaking their tooling.

Quick check

Does turning off introspection secure a GraphQL API?

No. It only makes reconnaissance harder. You still need authorization checks in every resolver.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.