Vulnerability

GraphQL Vulnerabilities
detect, understand, remediate

GraphQL APIs introduce unique security risks including introspection leaks, deeply nested query attacks, batching abuse, and field-level authorization gaps that can expose sensitive data or crash servers.

No credit card required. Free plan available forever.

Severity

High

CWE ID

CWE-200

OWASP Top 10

A01:2021 – Broken Access Control

CVSS 3.1 Score

8.2

What are GraphQL vulnerabilities?

GraphQL vulnerabilities (CWE-200) encompass a range of security weaknesses unique to GraphQL APIs, including unauthorized data exposure through introspection, denial of service via deeply nested or batched queries, broken access control at the resolver level, and injection attacks through unsanitized query variables. Unlike REST APIs where each endpoint has a defined scope, GraphQL provides a single endpoint that exposes the entire data graph, making the attack surface significantly larger.

GraphQL's strengths as a query language also create its most significant security challenges. The ability for clients to specify exactly which fields they want means that a misconfigured resolver can expose sensitive data that was never intended to be public. Nested relationships allow attackers to traverse the data graph in unexpected ways, accessing resources through indirect paths that bypass authorization checks. This makes GraphQL security fundamentally different from traditional REST API security, where access control is typically enforced per endpoint.

The growing adoption of GraphQL in production applications has made these vulnerabilities increasingly relevant. Organizations that migrate from REST to GraphQL often underestimate the security implications, carrying over REST-style authorization patterns that do not adequately protect a graph-based query interface. Combined with denial-of-service risks from unbounded query complexity and mass assignment through mutations, GraphQL deployments require specialized security measures beyond traditional web application defenses.

How it works

1

Discover GraphQL endpoint

The attacker identifies the GraphQL endpoint by testing common paths (/graphql, /gql, /api/graphql) or inspecting client-side JavaScript for query strings and endpoint URLs.

2

Run introspection query

If introspection is enabled, the attacker sends the __schema query to obtain the complete API schema, including all types, fields, mutations, and relationships, revealing the full attack surface.

3

Craft deeply nested or batched queries

Using the discovered schema, the attacker builds queries that exploit recursive relationships (user > posts > author > posts > author...) or batches hundreds of operations in a single request to exhaust server resources.

4

Extract data or overwhelm server

The crafted queries either extract sensitive data through overly permissive resolvers, bypass field-level authorization, or cause resource exhaustion that degrades service for all users.

Common causes

Introspection enabled in production

Leaving the introspection feature active in production environments exposes the entire API schema to any user, giving attackers a detailed map of every type, field, and relationship in the system.

Missing query depth and complexity limits

GraphQL servers that accept queries of unlimited depth and complexity are vulnerable to resource exhaustion. A single deeply nested query can generate millions of database queries through recursive relationship resolution.

No rate limiting or batching restrictions

Without per-operation rate limiting and batch size restrictions, attackers can send thousands of mutations in a single HTTP request, bypassing traditional rate limiting that operates at the request level.

Overly permissive resolvers

Resolvers that return all fields from the data source without checking whether the requesting user has permission to access each field. Authorization is applied at the query level but not at individual field or object resolvers.

How to detect it

Automated detection

  • SecPortal's authenticated scanning automatically discovers GraphQL endpoints, tests for introspection availability, and maps the full schema to identify overly permissive fields
  • Query complexity testing sends progressively deeper nested queries and larger batches to determine whether the server enforces depth limits, complexity budgets, and batch size restrictions
  • Automated introspection probing tests the endpoint with standard __schema and __type queries, as well as variations that bypass common introspection blocking patterns

Manual testing

  • Send an introspection query and use tools like GraphQL Voyager or GraphiQL to visualize the schema, identifying sensitive types (User, Payment, AdminConfig) that may expose internal data
  • Test field-level authorization by querying sensitive fields (email, SSN, role, balance) on other users' objects through relationship traversal, checking for horizontal access control gaps
  • Craft a query that nests the same relationship 20 or more levels deep and observe whether the server accepts it, times out, or returns an error indicating depth limits are enforced

How to fix it

Disable introspection in production

Turn off the introspection feature in production deployments. If internal tooling requires schema access, restrict introspection to authenticated admin users or internal network interfaces only.

Enforce query depth and complexity limits

Configure maximum query depth (typically 7 to 10 levels), a complexity budget that accounts for list fields and nested relationships, and per-query execution time limits to prevent resource exhaustion attacks.

Implement field-level authorization

Apply authorization checks at every resolver, not just at the query entry point. Use middleware or directives to enforce that users can only access fields and objects they are authorized to view or modify.

Use persisted queries

Restrict the server to only accept pre-registered query hashes instead of arbitrary query strings. This prevents attackers from crafting novel malicious queries and limits the API surface to known, reviewed operations.

Rate limit per operation

Apply rate limiting at the GraphQL operation level rather than the HTTP request level. Count individual queries and mutations within batched requests and enforce per-operation rate limits to prevent abuse through query batching.

Compliance impact

Secure your GraphQL API

SecPortal tests for introspection leaks, query complexity attacks, batching abuse, and broken field-level authorization. Start free.

No credit card required. Free plan available forever.