GraphQL security vulnerabilities expose APIs in ways traditional REST security controls miss. The five critical risks are: introspection enabled in production leaking your complete API schema, missing query depth limits enabling denial-of-service attacks, broken object-level authorization allowing cross-user data reads, unsanitized query arguments opening injection pathways, and directive-based authentication bypass. Unlike REST, GraphQL consolidates every operation through a single endpoint — one misconfiguration becomes a catastrophic exposure point. This guide covers each vulnerability, real attack impact, and the controls Indian development teams must implement.
Why GraphQL Rewrites the API Attack Surface
REST APIs distribute operations across discrete endpoints. A scanner probing /api/users/42 touches one resource. A scanner probing /graphql can enumerate your entire schema, chain deeply nested resolvers into computational bombs, and extract cross-table relationships in a single query.
GraphQL adoption in India has accelerated across fintech, B2B SaaS, edtech, and healthcare platforms — particularly on Node.js and Django stacks using Apollo Server or Strawberry. The developer experience benefits are real. The security defaults are not.
OWASP's API Security Top 10 (2023) places authorization failures and authentication breakdowns as the two most prevalent API vulnerability classes. GraphQL amplifies both, for two structural reasons:
- Schema self-documentation (introspection) makes reconnaissance trivial when enabled in production.
- Resolver independence means each data field requires its own authorization check — and teams routinely miss them under velocity pressure.
The GraphQL Attack Chain
Every successful GraphQL breach follows a predictable path. A well-hardened API breaks this chain at step one. An unprotected API concedes every step:
graph TD
A[GraphQL Endpoint Found]:::danger --> B[Introspection Query Sent]:::danger
B --> C{Introspection On?}:::normal
C -- Yes --> D[Full Schema Downloaded]:::danger
C -- No --> E[Field Enumeration]:::danger
D --> F[Target Fields Identified]:::danger
E --> F
F --> G[Deep Query Crafted]:::danger
G --> H{Auth Enforced?}:::normal
H -- Missing --> I[BOLA Data Extracted]:::danger
H -- Weak --> J[Directive Auth Bypassed]:::danger
I --> K[Privilege Escalation]:::danger
J --> K
classDef normal fill:#1e3a5f,stroke:#3B82F6,color:#e2e8f0
classDef danger fill:#5f1e1e,stroke:#EF4444,color:#e2e8f0
classDef success fill:#1e3d2f,stroke:#10B981,color:#e2e8f0Five Critical GraphQL Security Vulnerabilities
1. Introspection Enabled in Production
GraphQL introspection is a built-in mechanism that returns your complete schema when queried: every type, every field, every mutation, every relationship. In development, it powers tools like GraphiQL and Apollo Sandbox. In production, it hands attackers a free blueprint.
The query { __schema { types { name fields { name } } } } requires no authentication in most default configurations. An attacker submits it, reads the schema, and immediately identifies high-value targets — adminUser, paymentMethod, aadhaarRef, internalScore — without any prior knowledge of your codebase.
Fix: Set introspection: false in your Apollo Server production configuration. For other servers, strip schema and type at the validation layer. If partners need schema access, use a schema registry with authentication — never live introspection endpoints.
2. Missing Query Depth and Complexity Limits
GraphQL clients control query shape. Without server-side limits, an attacker crafts deeply nested queries that force thousands of database resolver calls from a single request:
{ users { friends { friends { friends { id email bankAccount { balance } } } } } }Each nesting level multiplies resolver invocations exponentially. This is a denial-of-service attack that bypasses traditional rate limiting entirely — it arrives as one valid HTTP POST. Standard IP-based throttling counts requests, not computational cost.
Fix: Implement query depth limits (typically 5–7 levels) using libraries such as graphql-depth-limit for Node.js. Add query complexity scoring via graphql-query-complexity. Set server-level execution timeouts as a backstop. These are baseline requirements, not optional hardening.
3. Broken Object-Level Authorization
Broken Object Level Authorization (BOLA) — also known as IDOR — is ranked the most common API vulnerability by OWASP. In GraphQL, it appears when resolvers fetch records by ID without verifying that the requesting user owns that record:
query { invoice(id: "INV-0087") { amount clientName bankDetails } }If the resolver executes db.invoices.findById(id) without checking record.userId === req.user.id, any authenticated user can access any invoice. In Indian fintech, healthcare, and B2B SaaS contexts, this directly exposes PII and payment data — and triggers obligations under the DPDP Act 2023.
Fix: Every resolver that fetches an object by ID must verify ownership or role before returning data. Use a centralized authorization layer rather than repeating checks per resolver. Enforce row-level security at the database layer where your ORM supports it.
4. Injection via GraphQL Arguments
GraphQL arguments are user-controlled inputs flowing into database queries, search functions, and downstream API calls. When argument values reach query engines without parameterization, they become injection vectors.
MongoDB injection is especially common in Node.js GraphQL stacks popular with Indian startups. An argument value like {"$gt":""} passed to a filter field can bypass authentication when the resolver does direct operator passthrough. SQL injection is equally possible when resolvers use raw string interpolation instead of ORM-level queries.
Fix: Enforce strict scalar types on all GraphQL arguments. Never concatenate argument values into query strings. Use ORM methods with parameterized binding. Apply input validation at the schema boundary using custom scalars or dedicated validation libraries.
5. Directive-Based Authentication Bypass
GraphQL directives — @include, @skip, @deprecated, and custom ones like @auth or @requiresRole — are legitimate schema features. The vulnerability emerges when authorization directives applied at the schema level are not also enforced inside resolver logic.
If a field is protected by @auth in the schema definition but the underlying resolver does not independently verify the user's session token, an attacker sending a raw HTTP POST to the endpoint — bypassing any client-side directive rendering — may access the field without authentication.
Fix: Treat schema-level directives as documentation, not security enforcement. Authorization must live in resolver middleware that executes before any business logic, using verified JWT or session tokens. The directive annotates; the resolver enforces.
GraphQL Vulnerability Distribution
The chart below shows the relative prevalence of vulnerability categories per OWASP API Security Top 10 (2023) ranking order, applied to GraphQL-specific attack scenarios. Authorization failures dominate because GraphQL's resolver model makes it straightforward to add new fields without inheriting consistent auth logic.
pie title GraphQL Vulnerability Types by Frequency
"Auth Bypass and BOLA" : 30
"Information Disclosure" : 25
"Injection Attacks" : 20
"DoS via Query Abuse" : 15
"Broken Authentication" : 10Know your vulnerabilities before attackers do
Run a free VAPT scan — takes 5 minutes, no signup required.
Book Your Free ScanBuilding a Secure GraphQL API
Security for GraphQL must be applied at multiple distinct layers. No single control is sufficient in isolation.
| Layer | Control | Implementation |
|---|---|---|
| Schema | Disable introspection | introspection: false in production config |
| Query | Depth and complexity limits | graphql-depth-limit, cost middleware, server timeouts |
| Authorization | Object-level resolver checks | Ownership verification on every ID-based query |
| Input | Argument sanitization | Strict scalar types, parameterized ORM queries |
| Transport | Rate limiting by user and IP | Separate query-cost limiter from request-count limiter |
| Monitoring | Query logging and anomaly alerts | Alert on queries exceeding complexity threshold |
A Five-Minute Self-Audit
Run these tests on your own API before an attacker does:
- Introspection check: POST
{"query":"{__schema{types{name}}}"}to your production endpoint. If types return, you have an immediate critical finding. - Depth limit check: Build a query nested 10 levels deep. If the server responds with data, depth limits are absent.
- BOLA check: Authenticate as User A, then request an object belonging to User B by its ID. If data returns, you have a BOLA vulnerability.
- Injection check: Pass
{"$gt":""}as a filter string argument. If it executes without error on a MongoDB backend, you have operator injection. - Rate-limit check: Send 50 parallel shallow requests. If no 429 errors occur, you lack basic HTTP rate limiting. Note that this is separate from query complexity limits (see Vulnerability 2) — both are required, and complexity limits must be configured independently of request-count throttling.
GraphQL Security and India's DPDP Act
GraphQL APIs in Indian fintech, healthcare, HR-tech, and B2B SaaS platforms routinely process personal data: Aadhaar-linked identifiers, bank account details, health records, and employee information. A BOLA vulnerability or introspection leak that exposes this data is not merely a technical finding — it is a reportable personal data breach under the Digital Personal Data Protection Act 2023.
Data fiduciaries must implement reasonable security safeguards to prevent breaches. A GraphQL API running with production introspection enabled, no depth limits, and resolver-level authorization gaps fails that standard on its face. Review your DPDP compliance posture in parallel with your GraphQL security assessment.
CERT-In's cybersecurity advisories and guidelines consistently emphasize securing API endpoints as part of India's digital economy infrastructure. Aligning with both CERT-In's published guidance and OWASP's API Security framework positions your product for regulatory confidence and enterprise customer trust.
Frequently Asked Questions
What is the most dangerous GraphQL vulnerability?
Should I disable GraphQL introspection in production?
How do GraphQL DoS attacks differ from standard API floods?
Is injection through GraphQL arguments a real risk for Node.js applications?
Does a GraphQL vulnerability trigger DPDP Act obligations in India?
How do I test my GraphQL API for introspection exposure in under five minutes?
{"query":"{__schema{types{name}}}"} and Content-Type: application/json. If the response contains a list of types, introspection is enabled in production. This single test takes under two minutes and reveals one of the most exploitable GraphQL misconfigurations.