Key Takeaways

  • Introspection exposes your entire API schema—disable it in production.
  • Nested queries can cause DoS through exponential complexity.
  • GraphQL doesn't have built-in rate limiting—you must implement it.
  • Batching attacks can bypass authentication rate limits.

GraphQL's flexibility is its greatest strength and weakness. Unlike REST, clients can request exactly what they need—or craft malicious queries that crash your servers. Let's explore every attack vector.

Why GraphQL Is Different

GraphQL provides a single endpoint (/graphql) where clients send queries describing the data they need. This paradigm shift brings new security challenges:

Attack #1: Introspection Exploitation

By default, GraphQL allows clients to query the schema itself:

# This query returns the ENTIRE API schema
{
  __schema {
    types {
      name
      fields {
        name
        type { name }
      }
    }
  }
}
Attack Impact

Attackers can discover:

  • Hidden admin mutations (deleteUser, escalatePrivileges)
  • Internal fields not meant for public use
  • Deprecated endpoints with known vulnerabilities
  • Complete data model for crafting IDOR attacks

Mitigation

# Apollo Server - Disable introspection in production
const server = new ApolloServer({
  typeDefs,
  resolvers,
  introspection: process.env.NODE_ENV !== 'production'
});

Attack #2: Query Complexity DoS

Deeply nested queries can cause exponential database load:

# This innocent-looking query can return millions of records
{
  users(first: 1000) {
    posts(first: 1000) {
      comments(first: 1000) {
        replies(first: 1000) {
          author {
            posts(first: 1000) {
              # Infinite nesting possible!
            }
          }
        }
      }
    }
  }
}

This query could attempt to load 1000 × 1000 × 1000 × 1000 = 1 trillion records.

Defense: Query Complexity Analysis

// Assign cost to each field
const typeDefs = `
  type User {
    id: ID!
    posts(first: Int): [Post!]! @cost(complexity: 10, multiplier: "first")
  }
`;

// Reject queries exceeding threshold
const server = new ApolloServer({
  validationRules: [
    createComplexityRule({
      maximumComplexity: 1000,
      onComplete: (complexity) => console.log('Query complexity:', complexity)
    })
  ]
});

Attack #3: Batching Brute Force

GraphQL allows sending multiple queries in a single request, bypassing rate limits:

# Single request containing 100 login attempts
[
  { "query": "mutation { login(email: \"[email protected]\", pass: \"password1\") { token } }" },
  { "query": "mutation { login(email: \"[email protected]\", pass: \"password2\") { token } }" },
  // ... 98 more attempts
]

Defense

  • Limit batch size: maxBatchSize: 5
  • Rate limit per operation type, not just requests
  • Implement query fingerprinting

Attack #4: SQL/NoSQL Injection

GraphQL doesn't prevent injection—it just changes the surface:

# Malicious GraphQL query
{
  user(id: "1 OR 1=1 --") {
    email
    password  # Might expose all users!
  }
}

Defense: Always Use Parameterized Queries

// VULNERABLE
const resolvers = {
  Query: {
    user: (_, { id }) => db.query(`SELECT * FROM users WHERE id = ${id}`)
  }
};

// SECURE
const resolvers = {
  Query: {
    user: (_, { id }) => db.query('SELECT * FROM users WHERE id = $1', [id])
  }
};

Attack #5: Field Suggestion Exploitation

Even with introspection disabled, field suggestions leak schema information:

# Response reveals valid field names
{
  "errors": [{
    "message": "Cannot query field 'pasword'. Did you mean 'password'?"
  }]
}

Security Checklist

ControlPriorityImplementation
Disable introspectionCriticalServer config
Query depth limitingCriticalValidation plugin
Query complexity analysisHighCost directives
Batch size limitsHighServer config
Field-level authCriticalResolver guards
Disable suggestionsMediumError handling

Frequently Asked Questions

Is GraphQL more secure than REST?
Neither is inherently more secure—they have different attack surfaces. GraphQL centralizes security concerns but introduces complexity-based attacks. REST spreads risk across endpoints but has well-understood patterns.
How do I scan for GraphQL vulnerabilities?
Use tools like GraphQL Voyager (schema visualization), InQL (Burp extension), graphql-cop (security scanning), and BatchQL (batch attack testing). Always check introspection first.

Secure your entire API layer.
Complete API Security Guide