Introspecção pública do GraphQL: por que é um problema e como desativá-la
A introspecção do GraphQL é a query embutida que retorna o schema completo da sua API: cada tipo, campo, argumento e mutation. Ela é essencial em desenvolvimento, mas não deveria estar acessível em produção em APIs privadas. Deixada ativada, ela é um mapa de toda a superfície de ataque do seu backend.
O que é
Todo servidor GraphQL implementa um pequeno conjunto de metacampos, principalmente __schema e __type. Um único POST para /graphql com `query { __schema { types { name fields { name } } } }` retorna a definição completa dos tipos.
Ferramentas como GraphiQL, Apollo Sandbox e a interface Playground dependem da introspecção para autocompletar queries e exibir o explorador do schema. Em desenvolvimento é exatamente isso que você quer; em produção, numa API privada, significa que qualquer pessoa no mundo pode baixar o mesmo mapa.
Por que importa
O schema nomeia os seus models, os seus relacionamentos e cada mutation que você expõe — incluindo campos administrativos, internos e obsoletos que nunca deveriam ser descobertos de fora. Atacantes o usam para montar uma lista direcionada de operações para testar falhas de bypass de autenticação, IDOR e injeção.
Mesmo que todos os campos estejam corretamente autorizados, mutations ocultas como refundOrder, impersonateUser ou exportBackup não deveriam se anunciar. A introspecção transforma a fase de reconhecimento do atacante de horas de tentativa e erro numa única requisição.
Como corrigir
Desligue a introspecção quando NODE_ENV for production. Mantenha-a ativada localmente para que a sua equipe ainda possa explorar o schema no Sandbox.
import { ApolloServer } from "@apollo/server";
const server = new ApolloServer({
typeDefs,
resolvers,
introspection: process.env.NODE_ENV !== "production",
});O Yoga tem um plugin oficial; o graphql-http expõe uma regra de validação do graphql-js. Ambos bloqueiam queries de introspecção antes que sejam executadas.
// GraphQL Yoga
import { createYoga } from "graphql-yoga";
import { useDisableIntrospection } from "@graphql-yoga/plugin-disable-introspection";
export const yoga = createYoga({
schema,
plugins: process.env.NODE_ENV === "production" ? [useDisableIntrospection()] : [],
});
// graphql-http (or express-graphql)
import { NoSchemaIntrospectionCustomRule } from "graphql";
const validationRules = process.env.NODE_ENV === "production"
? [NoSchemaIntrospectionCustomRule]
: [];GraphiQL, Playground e Apollo Sandbox existem para ajudar pessoas a explorar o schema — eles não têm lugar num endpoint público de produção. Proteja-os com uma verificação de autenticação ou simplesmente não os monte no build de produção.
Desativar a introspecção é uma medida de hardening, não controle de acesso. Cada campo ainda precisa de autorização adequada no nível do resolver — caso contrário, qualquer um que adivinhe o nome de um campo ainda consegue chamá-lo. Trate a introspecção como uma camada, não como a única camada.
FAQ
Esconder o schema não é só segurança por obscuridade?
Em parte, sim — um atacante determinado ainda pode descobrir nomes de campos por força bruta. Mas vale a pena não deixar o reconhecimento barato e completo. Todos os guias comerciais de APIs GraphQL e a cheat sheet de GraphQL da OWASP recomendam desativar a introspecção em produção.
E se for uma API pública em que eu quero que desenvolvedores explorem o schema?
Publique o schema de forma deliberada — disponibilize um arquivo em Schema Definition Language, hospede um site de documentação ou exponha a introspecção só depois da autenticação. Isso é muito diferente de um POST anônimo retornar tudo.
Como o AppSafe detecta isso?
O AppSafe envia via POST uma pequena query de introspecção para /graphql e /api/graphql e procura uma resposta __schema com status 200. Se ela voltar, o problema é sinalizado com severidade média na categoria Segurança de API.
Seu app está afetado?
O AppSafe verifica isso e dezenas de outros problemas em um único escaneamento grátis.
Escanear meu app grátisGuias relacionados
CORS mal configurado: as armadilhas do curinga e do reflexo
Permita toda origem e qualquer site poderá ler sua API.
Páginas de erro detalhadas e stack traces em produção
Um stack trace mostra ao atacante exatamente onde mirar.
Métodos HTTP perigosos: como TRACE, PUT e DELETE são anunciados
Uma resposta OPTIONS que lista TRACE ou DELETE revela mais do que deveria.
API keys expostas no JavaScript do cliente
Tudo no seu bundle é público. Trate assim.