Try the REST API Checker

GraphQL's Introspection Query Is an Attacker's Best Friend — Batching, Nested Query DoS, and Persisted Queries

GraphQL's introspection query exposes your complete schema — every type, field, and relationship — to anyone who can reach the endpoint, making it the most powerful reconnaissance tool an attacker can use against a GraphQL API. Here's batching attacks that bypass rate limiting, deeply nested queries causing 100^5 database lookups, persisted queries as a security pattern, and how to test GraphQL endpoints with a REST API checker.

July 19, 2026 6 min read
Share: Facebook WhatsApp LinkedIn Email
GraphQL's Introspection Query Is an Attacker's Best Friend — Batching, Nested Query DoS, and Persisted Queries

GraphQL's introspection query — a special query that asks an API to describe its own schema — is the most powerful reconnaissance tool an attacker can use against a GraphQL API, and many production GraphQL deployments have introspection enabled by default without realising what they've exposed

The previous articles on this site covered REST API basics, HTTP status codes, authentication methods, rate limiting, API versioning, and error-path testing. This article addresses GraphQL API security — specifically the attack surface that GraphQL introduces, how it differs from REST security, and the specific vulnerabilities that a REST API checker reveals in GraphQL endpoints.


GraphQL vs REST: a different attack surface

REST APIs have many endpoints (URLs), each with a specific purpose and defined input/output shape. Security focuses on each endpoint individually.

GraphQL APIs have a single endpoint (typically /graphql) that accepts complex queries. The client defines what data it wants; the server returns exactly that structure. Security must focus on the query itself, not individual URLs.

The attack surface differences:

REST GraphQL
Many URLs, each auditable Single URL, infinite query variations
Server defines response shape Client defines response shape
Over-fetching is a problem but not a security risk Deeply nested queries can cause DoS
Each endpoint has a clear attack surface Schema defines all possible queries simultaneously

The introspection vulnerability

GraphQL introspection is a built-in feature that allows clients to query the schema:

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

What this returns: the complete schema — every type, every field, every input argument. This is invaluable for developers building clients. It's equally invaluable for attackers mapping targets.

What an attacker learns:

  • Every query and mutation available (the full API surface)
  • Input field names and types (reducing guessing needed for injection tests)
  • Relationships between data types (understanding the data model)
  • Field names that suggest sensitive data (password, credit_card, ssn, admin_token)

Should introspection be disabled in production? The answer depends on whether you're building a public or private API. Public GraphQL APIs (GitHub's GraphQL API) leave introspection enabled because the schema is documentation. Private APIs serving internal clients or mobile apps should disable introspection in production environments — developers can use it in staging; attackers shouldn't have it in production.


Batching attacks and rate limiting bypass

GraphQL allows batching multiple queries in one request:

[
  {"query": "{ user(id: 1) { email } }"},
  {"query": "{ user(id: 2) { email } }"},
  ...
  {"query": "{ user(id: 1000) { email } }"}
]

The rate limiting problem: most rate limiting systems count HTTP requests — one request per second might be a limit. But a single batched GraphQL request can contain 1,000 individual queries. One HTTP request, 1,000 data lookups.

The credential stuffing variation: an attacker batching 1,000 login mutation attempts in a single request bypasses per-request rate limiting. A rate limiter that allows 10 requests per second is effectively allowing 10,000 login attempts per second.

Mitigation: GraphQL-aware rate limiting that counts individual operations within batched requests, or disabling batching entirely. Some GraphQL servers disable batching by default; others enable it.


Deeply nested queries: the DoS vector

GraphQL's recursive structure allows deeply nested queries:

{
  users {
    friends {
      friends {
        friends {
          friends {
            # continued 10 more levels deep
          }
        }
      }
    }
  }
}

The computational cost: each nesting level can multiply the data fetched. If "users" returns 100 records, and "friends" of each user also returns 100 records, and so on, 5 levels of nesting produces up to 100^5 = 10 billion database lookups from a single query. This is a self-inflicted DoS vulnerability.

Mitigations:

  • Query depth limiting: reject queries with more than N levels of nesting
  • Query complexity scoring: assign a complexity score to each field; reject queries above a total threshold
  • Amount limiting: cap the number of records returned at each level
  • Timeout: kill queries that exceed a computation time limit

Persisted queries: the security improvement

Persisted queries is a GraphQL security pattern where the server pre-approves a set of queries and clients can only execute those approved queries (referenced by hash):

Instead of:

{"query": "{ user(id: 1) { email } }"}

Clients send:

{"id": "abc123hash"}

The server looks up the pre-approved query associated with abc123hash and executes it.

Security benefit: attackers can't craft arbitrary queries — they can only use pre-approved operations. Introspection, batching attacks, and deeply nested query DoS become impossible because those queries aren't in the approved set.

The trade-off: reduces API flexibility for clients (they can't compose arbitrary queries) — acceptable for mobile apps and frontend clients that send known queries, not for developer exploratory access.


Testing GraphQL with the REST API checker

A REST API checker can test GraphQL endpoints because GraphQL uses HTTP POST with a JSON body:

Basic query test:

POST /graphql
Content-Type: application/json

{"query": "{ __typename }"}

Introspection test:

POST /graphql
Content-Type: application/json

{"query": "{ __schema { types { name } } }"}

If introspection returns schema data, introspection is enabled and should be evaluated for security appropriateness.

Authentication test: send a GraphQL query without authentication credentials and verify that protected fields return an authentication error, not data.


How to use the REST API Checker on sadiqbd.com

  1. GraphQL endpoint discovery: try POST to /graphql, /api/graphql, /v1/graphql with a minimal query body {"query":"{ __typename }"} — a valid GraphQL response confirms the endpoint exists
  2. Introspection security check: send the introspection query to a GraphQL endpoint you operate; if it returns the schema in production, evaluate whether introspection should be disabled
  3. Authentication bypass test: send a query for authenticated data without an Authorization header; any response returning data (rather than a 401 or "not authenticated" error) indicates missing authentication enforcement

Frequently Asked Questions

Should all public APIs use REST or is GraphQL ever the better security choice? Security is not a primary differentiator between REST and GraphQL — both can be implemented securely or insecurely. GraphQL's introspection and batching vulnerabilities are the unique security challenges to address, but REST's many endpoints and looser input validation have their own security challenges. The choice between REST and GraphQL should be made on API design and developer experience grounds, then security controls applied appropriately to whichever is chosen. GraphQL's persisted queries can actually make a tightly-controlled GraphQL API more secure than an equivalent REST API with many publicly-known endpoints — because only approved operations are executable.

Is the REST API Checker free? Yes — completely free, no sign-up required.

Try the REST API Checker free at sadiqbd.com — test any REST or GraphQL API endpoint with custom headers, body, and authentication.

Share: Facebook WhatsApp LinkedIn Email

REST API Checker

Free, instant results — no sign-up required.

Open REST API Checker →
Similar Tools
Number Base Converter Regex Tester JSON Diff Hash Generator URL Encoder/Decoder Base64 Encoder/Decoder JSON Formatter JWT Decoder
API Authentication Methods Compared: Keys, Bearer Tokens, OAuth 2.0, and HMAC
Developer
API Authentication Methods Compared: Keys, Bearer Tokens, OAuth 2.0, and HMAC
API Rate Limiting: How It Works, How to Read Rate Limit Headers, and Exponential Backoff Strategies
Developer
API Rate Limiting: How It Works, How to Read Rate Limit Headers, and Exponential Backoff Strategies
API Versioning: URL Paths, Headers, Query Strings, and Why "Just Change the Endpoint" Always Comes Back to Haunt You
Developer
API Versioning: URL Paths, Headers, Query Strings, and Why "Just Change the Endpoint" Always Comes Back to Haunt You
The Most Revealing API Tests Aren't Successful Requests — A Systematic Error-Path Testing Guide
Developer
The Most Revealing API Tests Aren't Successful Requests — A Systematic Error-Path Testing Guide