Como funciona esta verificação
O Scanaris envia um pedido POST com a consulta de introspeção mais pequena possível, {__schema{queryType{name}}}, a três caminhos onde costuma viver um endpoint GraphQL: /graphql, /api/graphql e /v1/graphql. Se algum responder 200 e o corpo contiver __schema ou queryType, a introspeção está ativa e abre um achado de severidade média com o caminho. Se não há GraphQL no teu site, nenhum caminho responde assim e não há achado. A consulta é só de leitura, não toca em dados, e passa pelos mesmos limites de tempo e tamanho do resto da análise.
Porque importa
A introspeção é a função do GraphQL que permite perguntar à API pelo seu próprio esquema: todos os tipos, todos os campos de cada tipo, todas as consultas e mutações disponíveis, com os seus argumentos. Em desenvolvimento é imprescindível: é o que usam o playground, o autocompletar do editor e os geradores de código. Em produção, aberta a qualquer um, é um mapa completo do teu backend. Um atacante vê que existe uma mutação deleteUser(id) ou um campo internalNotes sem ter de os adivinhar, e vai direto testar se a autorização de cada um está bem feita. Por isso é severidade média: não expõe dados por si só, mas torna trivial encontrar qualquer outra falha de permissões.
Como desativá-la em produção
- Apollo Server:
introspection: "production" !== 'production'ao criar o servidor. Desde o Apollo 4 já vem desativada quandoNODE_ENVéproduction; se a vires ativa, confirma que essa variável chega ao teu deploy. Desativa também a landing page ou o playground em produção. - GraphQL Yoga e Envelop: o plugin
useDisableIntrospection()de@envelop/disable-introspection, condicionado ao ambiente. - Hasura (o caminho /v1/graphql): nas definições de segurança do projeto há um controlo de introspeção por papel (Cloud e Enterprise). Garante ainda que o papel público tem permissões mínimas e que o segredo de administrador nunca viaja até ao browser.
- graphql-ruby:
disable_introspection_entry_pointsna classe do esquema. - Python (Graphene, Strawberry, Ariadne): adiciona a regra
NoSchemaIntrospectionCustomRuledographql-coreàs regras de validação em produção. - .NET (Hot Chocolate):
.AllowIntrospection(false)ou a opção de alterar a introspeção por pedido conforme um cabeçalho ou um papel.
Desativar a introspeção não substitui a autorização: cada consulta e mutação deve verificar quem pergunta. Acompanha-a de limites de profundidade e complexidade de consulta (evitam consultas aninhadas que deitam o servidor abaixo) e, se o teu servidor o permitir, desativa também as sugestões de campos ("Did you mean…"), que deixam fugir nomes mesmo com a introspeção fechada.
Confirma que está corrigido
curl -s -X POST https://teudominio.com/graphql -H "Content-Type: application/json" -d '{"query":"{__schema{queryType{name}}}"}'
Repete com /api/graphql e /v1/graphql. Esperado: um erro do tipo "introspection is not allowed", um 400 ou 403, ou um 404 se não há GraphQL aí. Se vires "queryType":{"name":"Query"}, continua aberta.
Perguntas frequentes
A minha API é pública e está documentada. Afeta-me?
Se publicas o esquema de propósito, a introspeção aberta não revela nada de novo e podes dar o achado por aceite. A maioria das APIs de aplicações não está nesse caso: têm mutações internas que ninguém devia conhecer.
O meu endpoint está noutro caminho. Não é verificado?
Só se testam os três caminhos mais comuns. Se o teu vive noutro, faz o teste de cima com o teu caminho real. Outros painéis e endpoints de desenvolvimento que não deviam responder em produção são procurados por endpoints expostos.
E se o endpoint pedir autenticação?
Então a introspeção responde 401 e não é marcada. É a situação correta: um atacante sem sessão não obtém o esquema. Confirma que o cabeçalho CORS da API não está aberto a qualquer origem; isso é visto por CORS permissivo.