GraphQL Batching Attack
GraphQL endpoints accepting arrays of operations without size limits, enabling attackers to bypass rate limiting by bundling thousands of requests into a single HTTP call.
How It Works
GraphQL supports batching — sending an array of operations in one HTTP request. Batching is meant for performance, but without size limits, attackers batch thousands of login attempts or resource requests into one HTTP call. Your rate limiter sees one request and lets it through, but the server executes thousands of operations.
// BAD: batching with no size limit
// Attacker sends: [{query: 'mutation login(email:"a"...)'}, {query: ...}, ...x1000]
app.post('/graphql', graphqlHTTP({ schema }));
// Rate limiter sees 1 request, but server runs 1000 mutations// GOOD: limit batch size
app.post('/graphql', (req, res, next) => {
const body = req.body;
if (Array.isArray(body) && body.length > 10) {
return res.status(400).json({ error: 'Batch size limit exceeded' });
}
return graphqlHTTP({ schema })(req, res, next);
});Real-World Example
GraphQL batching was used to bypass SMS OTP rate limiting on several major platforms — attackers could try hundreds of OTP codes in a single batched request. HackerOne has documented multiple bounty payouts for this issue.
How to Prevent It
- Limit batch size to a small number (5-10 operations per request)
- Consider disabling batching entirely if your clients don't use it
- Apply rate limiting per operation within a batch, not per HTTP request
- Use a GraphQL server that supports operation-level rate limiting (Apollo Router, GraphQL Armor)
Affected Technologies
Data Hogo detects this vulnerability automatically.
Scan Your Repo FreeRelated Vulnerabilities
API Documentation Exposed in Production
lowSwagger UI, ReDoc, or other API documentation interfaces publicly accessible in production, giving attackers a free interactive map of every endpoint, parameter, and authentication method.
GraphQL Introspection Enabled in Production
mediumGraphQL introspection is left enabled in production, allowing anyone to query the complete schema and discover all types, fields, mutations, and their argument structures.
GraphQL Without Query Depth Limit
mediumGraphQL API with no depth limit on nested queries, allowing attackers to craft deeply nested queries that exhaust server resources and cause denial of service.
Excessive Data Exposure
mediumAPI endpoints returning full database objects with sensitive fields instead of only the fields the client actually needs, exposing password hashes, internal IDs, admin flags, and other sensitive data.