Skip to main content
GraphQL lets a client ask for exactly the fields it needs through a single endpoint, instead of hitting a different REST route per resource. That flexibility is also what makes it awkward to secure: one endpoint now fronts the entire data graph, authorization has to be checked per-field rather than per-route, and the query language itself gives an attacker primitives (aliases, fragments, introspection) that a REST API never exposes.

Schema Discovery

Find the endpoint, confirm it’s GraphQL, then pull the full schema via introspection, or reconstruct it another way if introspection is disabled.

Abuse the Query Language

Batching, aliasing, and injection through resolvers exploit things that are a normal part of GraphQL, not a bug in any one implementation.

Finding the Endpoint

GraphQL servers are usually found at a predictable path, worth a quick bruteforce pass if it’s not obvious from the app itself (check requests in Burp/DevTools first, most front-end apps call it directly).
Queries are usually sent as a URL parameter on GET, or as a JSON body on POST, confirm which the target accepts.
graphiql and graphql/console are built-in IDEs some frameworks ship for development, if either is reachable in production it’s an instant win: full interactive schema browsing and query execution with no further work needed.

Confirming the Service

A universal query every GraphQL implementation understands, if it comes back instead of a 404 or a parse error, you’ve got a live endpoint.
A positive response looks like:

Introspection

Introspection is a built-in GraphQL feature that lets the schema describe itself, every type, field, and argument, to the caller. It’s meant for tooling during development, but plenty of APIs ship to production with it still enabled.
The expanded version also pulls argument names, descriptions, and types, enough to actually construct valid queries and mutations against fields you’ve never seen documented anywhere.
Running the full introspection query by hand is slow. InQL (Burp extension) sends it for you and renders the whole schema as a browsable tree, plus generates template queries/mutations for every field it finds.

When Introspection Is Disabled

Disabling introspection in production is a common hardening step, but it doesn’t make the schema unknowable, just slower to recover.
Most GraphQL servers return a helpful “Did you mean?” error when a query references a field that doesn’t exist but is close to one that does. Querying a deliberately wrong field name one character at a time and reading these suggestions back lets an attacker reconstruct the schema field-by-field without ever calling __schema.
Clairvoyance automates this exact process, reconstructing 60-80% of a schema this way is typical even with introspection fully disabled and no error-suggestion field left un-patched.
If field-suggestion errors are also disabled, falling back to a wordlist of common GraphQL type/field names (user, email, password, isAdmin, role, id…) brute-forced against the endpoint still recovers a usable partial schema, slower and noisier, but effective against a fully locked-down target.

Batching and Alias Abuse

GraphQL lets a single HTTP request bundle many separate operations, and lets the same field be queried multiple times under different names (aliases) in one request. Both are legitimate performance features, intended to save round-trips, and both turn into a single request doing the work of dozens. Query batching sends an array of operations instead of one:
Aliasing achieves the same multiplication inside a single operation, useful specifically for brute-forcing a login mutation past a rate limiter that only counts HTTP requests, not resolver calls:
A naive rate limiter counting requests-per-second sees exactly one request either way, hundreds of login attempts (or database reads) can be smuggled through in a single HTTP call. BatchQL automates finding and exploiting both patterns against a target endpoint.

Denial of Service via Query Complexity

Because a query can reference its own type recursively through nested relationships (a user has posts, each post has an author, that author has posts…), a deeply nested or circular query can force the server to do exponentially more work than the request size suggests.

Injection Through Resolvers

GraphQL is just a query layer in front of whatever datastore the backend actually uses, if a resolver passes an argument straight into a SQL query, a NoSQL filter, or a shell command without parameterizing it, the underlying injection class applies exactly as it would through a REST parameter. The abstraction layer just makes it easier to miss during a code review.
See Command Injection and the SQL injection page for the actual exploitation techniques once a resolver argument is confirmed to be inserted into a query unsanitized, GraphQL only changes where the payload is delivered from.

Authorization Bypass (BOLA / BFLA / Mass Assignment)

The classic IDOR, applied to GraphQL: a query accepts an object ID and returns that object’s data without checking whether the caller actually owns it. Exactly the same vulnerability as REST IDOR (see IDOR), just reached through a query field instead of a URL query.
A mutation meant for admins (deleteUser, promoteToAdmin) that the schema exposes to every authenticated caller, with authorization only enforced in the UI, not the resolver itself. Worth testing every mutation introspection reveals against a low-privilege session, not just the ones the app’s own UI calls.
A mutation’s input type accepts more fields than the client UI ever sends, if role or isAdmin is a field on the UserInput type, nothing stops a raw request from setting it directly even though the real form never exposes that control.

Quick Reference Tools

HackTricks: GraphQL

Reference used for this page.

InQL

Burp extension for schema dumping, attack-graph rendering, and query generation.

Clairvoyance

Reconstructs a GraphQL schema from field-suggestion errors when introspection is disabled.

BatchQL

Automates batching and alias-abuse attacks, including DoS and brute-force testing.

graphql-cop

Automated baseline security checks against a GraphQL endpoint (introspection, batching, CSRF, field suggestions).

GraphQL Voyager

Interactive visualization of a dumped schema, useful for spotting unexpected relationships fast.