RoastMyOpsec

Vulnerabilities

GraphQL Introspection vs Production APIs

January 29, 2024

GraphQL introspection vs production APIs is a schema-publication choice, not an automatic CVE. Introspection lets clients query __schema and learn types, fields, and arguments. That is appropriate for public developer platforms and a miss for private product APIs that never meant to publish the catalog. Turning introspection off does not replace authentication, authorization, or query cost limits. RoastMyOpsec's app-mode check sends one bounded, unauthenticated, read-only introspection POST to /graphql. It does not dump your data or brute-force resolvers.

The practical difference

A REST OpenAPI file you chose to publish is similar: documentation is not RCE. The OPSEC question is whether strangers should get a complete field list for an authenticated product graph.

Introspection on is convenient for GraphiQL in staging. Production private APIs usually disable it and keep schema docs in an authenticated developer portal.

How to choose based on the API's job

If the GraphQL endpoint is a public platform with documented types, introspection can stay on behind rate limits. If it backs a logged-in SaaS, disable introspection in production and require auth on every operation. Nested queries still need depth and complexity limits either way.

API typeIntrospection in prodStill requiredTakeaway
Public developer graphOften onAuth where data is private; rate limitsThe schema is a product
Private SaaS /graphqlUsually offAuthz on every field classDo not publish the menu
Staging onlyOn behind VPN or basic authDo not copy the flag to prodSame binary, different config
Federated graphsPer subgraph policyGateway still needs cost limitsOne open subgraph can narrate the rest

When disabling introspection is not enough

Field suggestions, error messages, and unauthenticated mutations are separate issues. A locked schema with open resolvers is still a data problem.

Pair production config with boring errors, persisted queries if you use them, and WAF/rate limits on /graphql.

Common mistakes

The first mistake is leaving the default 'introspection on' from a tutorial.

The second mistake is disabling introspection and calling the API 'private' with no auth on queries.

The third mistake is exposing GraphiQL on the production host.

Free audit the URL you own

RoastMyOpsec is a defensive public-surface roast: headers, cookies, sensitive paths, and more — no exploit payloads. Start with the free audit, then open the vault if the blurred findings look expensive.

Free audit now

FAQ

Is GraphQL introspection a vulnerability?
Usually no. It is information disclosure. It becomes urgent when the graph is private and the schema reveals admin-only types you did not intend to advertise.
Does turning introspection off hide all types?
No. Clients can still learn from errors, suggested fields, and any types they are allowed to query. Authorization still has to be real.
How does RoastMyOpsec test GraphQL?
One bounded unauthenticated POST with a read-only __schema query to /graphql. No mutation payloads, no nested attack queries.

Sources

Related guides