---
title: "Lock down GraphQL endpoints · Agent Wranglers"
url: https://agentwranglers.se/playbook/adversarial-testing/abuse-and-limits/graphql-endpoints
updated: 2026-10-21
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Lock down GraphQL endpoints

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Abuse and limits](https://agentwranglers.se/playbook/adversarial-testing/abuse-and-limits.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers). Updated 2026-10-21.

- ID: SEC-102
- Level: Recommended
- Chapter: [Abuse and limits](https://agentwranglers.se/playbook/adversarial-testing/abuse-and-limits)
- Rule: In production, turn off GraphQL introspection and field suggestions. Count every aliased or batched operation as its own request, and check access on every object a query reaches.
- How: Skip this rule when you run no GraphQL API. One request can hold hundreds of operations through aliases or a batch array. A rate limit that counts HTTP requests then lets one request guess hundreds of passwords or codes. Count each login, code check or other costly field as its own attempt inside the resolver. Refuse a query with more than 15 aliases. Cap depth and cost as [cap the size of every request and answer](https://agentwranglers.se/playbook/adversarial-testing/abuse-and-limits/resource-limits) says. Run the check from [check ownership on every record](https://agentwranglers.se/playbook/adversarial-testing/access-and-accounts/object-access) in the resolver of each object. That includes objects reached through `node` and nested fields, not only the top of the query. Hide error details as [show short errors](https://agentwranglers.se/playbook/adversarial-testing/data-and-secrets/short-errors) says.
- Check: On the test copy, send the query `{ __schema { types { name } } }` and a query with a misspelled field. Neither answer lists types or suggests a field name. Send one request with 50 aliased logins for a test account. Attempts past the limit in [slow down password guessing](https://agentwranglers.se/playbook/adversarial-testing/access-and-accounts/login-guessing) fail, as with 50 separate requests. As test user A, ask for user B's record through a nested field and through `node(id:)`. Both return no data.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### Plain text example

```graphql
# One request, many guesses: each alias must count as one login attempt
mutation {
  a1: login(email: "test@example.com", password: "guess1") { token }
  a2: login(email: "test@example.com", password: "guess2") { token }
}
```

### JavaScript example

```js
// Apollo Server: introspection off in production, depth capped, each login counted
import { ApolloServer } from '@apollo/server';
import depthLimit from 'graphql-depth-limit';

const server = new ApolloServer({
  typeDefs, resolvers,
  introspection: process.env.NODE_ENV !== 'production',
  validationRules: [depthLimit(10)],
});
const login = async (_, { email, password }, ctx) => {
  await loginLimiter.consume(`${ctx.clientAddress}:${email}`);
  return checkPassword(email, password);
};
```

### Python example

```python
# Strawberry: introspection off, depth and aliases capped
import strawberry
from graphql.validation import NoSchemaIntrospectionCustomRule
from strawberry.extensions import AddValidationRules, MaxAliasesLimiter, QueryDepthLimiter

schema = strawberry.Schema(query=Query, mutation=Mutation, extensions=[
    AddValidationRules([NoSchemaIntrospectionCustomRule]),
    QueryDepthLimiter(max_depth=10),
    MaxAliasesLimiter(max_alias_count=15),
])
```

## Sources

- [OWASP GraphQL Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/GraphQL_Cheat_Sheet.html)

## Related rules

- [Cap the size of every request and answer](https://agentwranglers.se/playbook/adversarial-testing/abuse-and-limits/resource-limits) in Security testing
- [Check ownership on every record](https://agentwranglers.se/playbook/adversarial-testing/access-and-accounts/object-access) in Security testing
- [Show short errors](https://agentwranglers.se/playbook/adversarial-testing/data-and-secrets/short-errors) in Security testing
- [Slow down password guessing](https://agentwranglers.se/playbook/adversarial-testing/access-and-accounts/login-guessing) in Security testing

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/adversarial-testing/abuse-and-limits/graphql-endpoints">Agent Wranglers security testing playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Confirm payments on the server](https://agentwranglers.se/playbook/adversarial-testing/abuse-and-limits/confirm-payment-server-side)
- [Abuse and limits](https://agentwranglers.se/playbook/adversarial-testing/abuse-and-limits)
