← All cybersecurity posts

GraphQL Security: Common Vulnerabilities and How to Test Them

GraphQL gives clients flexible access to data through a single endpoint. That flexibility changes the security picture: instead of many endpoints with fixed responses, you have one endpoint where clients decide what to ask for.

Introspection

GraphQL can describe its own schema via introspection queries. In production, this hands attackers a complete map of types, fields and mutations, including ones the frontend never uses.

Defence: disable introspection in production for private APIs. Note that schema details can still leak through error suggestions, such as "Did you mean adminUsers?", so disable field suggestions too.

Authorisation at the resolver level

The most serious GraphQL bugs are authorisation failures. Because clients can traverse relationships, a check on the top-level query is not enough:

query {
  me {
    organization {
      members { email }
      invoices { total }
    }
  }
}

If organization.invoices does not check the caller's permissions, any member, or a user reaching the organisation through another path, may see data they should not.

Defence: enforce authorisation in every resolver, or in a data access layer that all resolvers use, never only at the entry point.

Node and ID lookups

Relay-style APIs often expose node(id:), which fetches any object by global ID. This is a classic BOLA risk.

Defence: apply the same per-object authorisation in the node resolver as anywhere else.

Denial of service through query complexity

Clients can write deeply nested or expensive queries:

query { user { friends { friends { friends { friends { name } } } } } }

Defences:

  • Maximum query depth.
  • Query complexity or cost analysis.
  • Pagination limits on lists.
  • Timeouts and resource limits.
  • Persisted queries, allowing only known queries in production.

Batching and aliasing attacks

GraphQL lets clients send many operations in one request, using arrays or aliases:

mutation {
  a1: login(email: "[email protected]", password: "pass1") { token }
  a2: login(email: "[email protected]", password: "pass2") { token }
}

This can bypass rate limits that count HTTP requests, enabling brute force of passwords or one-time codes.

Defence: rate limit by operation, not by request, and limit aliases and batch sizes.

Injection

Arguments in GraphQL are still user input. Resolvers that build SQL, NoSQL or shell commands from arguments are vulnerable to injection just like REST handlers.

CSRF on GraphQL

If your GraphQL endpoint accepts cookie authentication and allows GET requests or application/x-www-form-urlencoded bodies, CSRF may be possible. Require application/json and use CSRF protections.

GraphQL security checklist

ControlPurpose
Introspection and suggestions off in productionReduce schema exposure
Resolver-level authorisationPrevent data leaks through relationships
Depth and complexity limitsPrevent DoS
Operation-level rate limitsStop batching abuse
Input validationPrevent injection
JSON-only requestsReduce CSRF

Testing GraphQL

SecurityInfinity's API agent detects GraphQL endpoints, extracts the schema where possible, tests resolvers for authorisation with multiple identities, and checks depth, batching and injection. Start free.

Frequently asked questions

Is GraphQL less secure than REST?

Not inherently, but it shifts risks. Authorisation and resource consumption need more deliberate design.

Does disabling introspection secure a GraphQL API?

No. It reduces information exposure but attackers can still discover fields through other means. Authorisation is what protects data.

What are persisted queries?

A list of pre-approved queries stored on the server. Clients send a query ID instead of arbitrary query text, which blocks unexpected and expensive queries.

Find what attackers can see, before they do.

AI pentesting agents test your web app, API and cloud, and every finding comes with evidence and a fix. First report in about 10 minutes.

Stay ahead of attackers.

New vulnerabilities, breach write-ups and practical fixes. A few emails a month.