Security Glossary

GraphQL Batching Attack

Exploiting GraphQL's batch operation capability to bypass rate limiting, brute-force credentials in single requests, or cause denial of service.

GraphQL Batching Attack exploits GraphQL's ability to execute multiple operations in a single request. Attackers abuse this to bypass rate limiting, brute-force credentials, or cause denial of service.

Attack Types

Query Batching for Brute Force

# Single request tests multiple credentials
[
  {"query": "mutation { login(user:\"admin\", pass:\"password1\") { token }}"},
  {"query": "mutation { login(user:\"admin\", pass:\"password2\") { token }}"},
  {"query": "mutation { login(user:\"admin\", pass:\"password3\") { token }}"},
  # ... hundreds more in one request
]

Alias-Based Batching

# Aliases pack many calls to the same field into one operation.
# Even when array batching is disabled, aliases still work:
query {
  a1: login(user: "admin", pass: "pass1") { token }
  a2: login(user: "admin", pass: "pass2") { token }
  a3: login(user: "admin", pass: "pass3") { token }
  # ... continue with more aliases
}

Why It Works

Rate limiting and lockout counters usually key on the number of HTTP requests. Batching moves the attack inside a single request: one request, hundreds of login or OTP attempts, one increment on the counter. The guard never fires.

Security Impact

  • Rate limit and lockout bypass (one request, many operations)
  • Credential brute forcing at scale
  • OTP/2FA code enumeration (a full 000000-999999 sweep in few requests)

Prevention

  • Cap the number of operations per request: reject arrays over a small batch size and limit how many aliases may target the same sensitive field
  • Rate limit and count lockout attempts by operation, not by HTTP request, so batched attempts still trip the counter
  • Enforce sensitive counters (login attempts, OTP verifications) in the resolver itself, where each individual operation is visible

Batch size is separate from query depth and complexity limits. Those defend against a single deeply nested query exhausting the backend, a different abuse than firing many shallow operations in one request. Apply both.

See Also