GraphQL Security Risks and Controls
GraphQL is a query language and runtime for APIs that grants clients fine-grained control over data fetching, distinguishing it sharply from REST-based interfaces. That flexibility introduces a distinct attack surface not fully addressed by controls designed for conventional HTTP APIs. This page maps the principal security risks associated with GraphQL deployments, the technical mechanisms behind each, the scenarios in which organizations encounter them, and the decision boundaries that shape control selection.
Definition and scope
GraphQL, published as an open specification by the GraphQL Foundation (hosted under the Linux Foundation), defines a schema-first API architecture where clients specify exactly which fields, relationships, and nested objects they want returned. The server exposes a single endpoint — typically /graphql — and processes structured query documents against a typed schema.
The security scope of GraphQL is distinct from general API security best practices because the query model itself is the primary attack surface. GraphQL allows deeply nested queries, introspection of the full schema, batched operations, and arbitrary field selection — capabilities that REST endpoints do not expose by default. The OWASP Top Ten Vulnerabilities taxonomy directly applies (broken access control, injection, security misconfiguration), but GraphQL-specific controls are required above and beyond those baselines.
Regulatory scope intersects GraphQL wherever APIs handle sensitive data. The Health Insurance Portability and Accountability Act (HIPAA) Security Rule at 45 CFR §164.312 requires access controls and audit logging for electronic protected health information regardless of the API protocol. PCI DSS v4.0 Requirement 6.4 mandates protection of public-facing web applications, which includes GraphQL endpoints processing payment data. NIST SP 800-53 Rev 5 (control families AC, AU, SC) applies to federal systems using GraphQL for data exchange.
How it works
GraphQL processes client requests through a schema resolution pipeline. Understanding that pipeline at a structural level is prerequisite to identifying where controls must be applied.
- Schema definition — The server defines all queryable types, fields, mutations, and subscriptions in a schema definition language (SDL) file. Every resolvable object is declared here, creating a blueprint attackers can enumerate.
- Introspection — By default, GraphQL exposes the
__schemaand__typeintrospection system, allowing any client to query the full type graph. This is standard behavior per the GraphQL specification and is the primary reconnaissance vector. - Query parsing and validation — Incoming query documents are parsed into an abstract syntax tree and validated against the schema before execution. Validation occurs server-side, but complexity limits are not enforced by default in most runtimes.
- Resolver execution — Each requested field is resolved independently by server-side resolver functions. Authorization logic must be implemented within or adjacent to each resolver; GraphQL provides no built-in authorization layer.
- Response serialization — The server assembles a JSON response mirroring the requested shape. Over-fetching of fields is prevented only if field-level access control is explicitly coded.
The separation between query validation and authorization at the resolver level is the architectural root of GraphQL's primary access control risks. This is fundamentally different from REST, where HTTP verb restrictions and resource-path ACLs provide a coarser but often sufficient first-line defense. For a broader view of authorization architecture, see authentication and authorization security.
Common scenarios
Introspection abuse — Exposed introspection endpoints allow unauthenticated attackers to enumerate the full data model before mounting targeted attacks. Production deployments at organizations including Shopify, HackerOne, and GitLab have surfaced sensitive field names through introspection in bug bounty programs reported via their public programs.
Denial-of-service through query complexity — GraphQL permits recursive and deeply nested queries. A single malicious query can request 10 levels of nested relationships, each expanding to hundreds of objects, generating database load exponentially larger than the query document suggests. Without query depth limiting or complexity scoring, a single authenticated (or unauthenticated) request can saturate a database.
Batching attacks — GraphQL supports batching multiple operations in a single HTTP request. This enables credential stuffing or brute-force attacks that bypass rate limiting applied at the HTTP layer, because 100 login mutation attempts arrive as one HTTP request. This intersects with injection attack prevention controls when mutation payloads carry malicious input.
Broken object-level authorization — Resolvers that return objects based on client-supplied IDs without ownership validation expose data belonging to other users. This mirrors the OWASP API Security Top 10 (2023 edition, published by OWASP Foundation) API1:2023 — Broken Object Level Authorization.
Schema stitching and federation risks — In federated GraphQL architectures (as defined by the Apollo Federation specification and the GraphQL Foundation's Working Group proposals), subgraph services may lack independent authorization controls, trusting the gateway to enforce policy. A compromised gateway or misconfigured subgraph exposes internal service data. This aligns with microservices security risk patterns.
Insecure direct object references in subscriptions — WebSocket-based GraphQL subscriptions maintain persistent connections. If subscription authorization is not re-validated after initial connection, a user whose permissions change mid-session may continue receiving unauthorized event streams.
Decision boundaries
Selecting controls requires mapping each risk to the architectural layer where it is addressable.
| Risk | Primary Control Layer | Secondary Control |
|---|---|---|
| Introspection exposure | Server configuration | Environment-based toggle (disable in production) |
| Query complexity DoS | Query depth/complexity limits | WAF rule supplementation |
| Batching brute force | Batch size limits | Rate limiting per operation, not per HTTP request |
| Object-level authorization | Resolver-level authorization | Field-level middleware (e.g., graphql-shield) |
| Federation trust abuse | Subgraph authentication | mTLS between gateway and subgraphs |
| Subscription re-auth | Connection lifecycle hooks | Token expiry enforcement at subscription level |
Introspection should be disabled in production and restricted to authenticated internal tooling in development environments — a distinction the GraphQL Foundation's own security guidance explicitly recommends. Query depth limiting is implemented differently across runtimes: graphql-depth-limit for Node.js, graphene extensions for Python, and graphql-java instrumentation for JVM environments; control selection depends on the server runtime, not on a universal standard.
For operations undergoing formal assessment, web application security testing methodologies should include GraphQL-specific test cases: introspection queries, alias-based batching, fragment cycles, and resolver-level authorization bypass attempts. Static analysis via secure code review should target resolver implementations for missing ownership checks. The application security posture management function is responsible for tracking whether introspection controls and complexity limits are consistently enforced across all deployed GraphQL services.
Query allowlisting — also called persisted queries or trusted documents — represents the strongest architectural control: the server accepts only pre-registered query hashes rather than arbitrary query documents. This approach eliminates introspection abuse and complexity attacks entirely but requires client-side coordination and is incompatible with ad-hoc GraphQL exploration tooling.
References
- GraphQL Foundation — specification and working group publications
- OWASP API Security Top 10 (2023) — OWASP Foundation
- NIST SP 800-53 Rev 5 — Security and Privacy Controls for Information Systems — National Institute of Standards and Technology
- HIPAA Security Rule, 45 CFR §164.312 — U.S. Department of Health and Human Services
- PCI DSS v4.0 — PCI Security Standards Council
- Linux Foundation — governance body for the GraphQL Foundation