# GraphQL query depth limited

- **Pattern:** `ab-000393` (`api-security.abuse-prevention.graphql-depth-limit`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000393
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000393)

## Why it matters

GraphQL's type system allows clients to construct arbitrarily nested queries — a feature designed for flexibility that becomes a denial-of-service vector without depth limiting. CWE-400 (Uncontrolled Resource Consumption) and OWASP API Security Top 10 2023 API4 (Unrestricted Resource Consumption) both apply. A deeply nested query like `{ author { posts { comments { author { posts { comments { ... } } } } } } }` triggers exponential database joins with each additional level. Unlike REST, where resource boundaries are fixed in the URL, GraphQL puts the query structure in the client's hands. Depth limiting is a server-side control that caps the structural complexity a client can demand regardless of individual field costs.

## Severity rationale

Low because GraphQL depth attacks require a valid query and authenticated access, but the resource cost of deeply nested queries scales exponentially with depth.

## Remediation

Add a depth-limiting validation rule to your GraphQL server at startup. A limit of 7–10 levels covers most legitimate use cases while blocking exponential fan-out queries.

```ts
// src/lib/graphql/server.ts
import { createComplexityLimitRule } from 'graphql-validation-complexity'
import depthLimit from 'graphql-depth-limit'

const server = new ApolloServer({
  schema,
  validationRules: [
    depthLimit(7),  // reject queries deeper than 7 levels
    createComplexityLimitRule(1000)  // optional: cost-based limit
  ]
})
```

If you don't use Apollo, pass `validationRules` to `graphql-js`'s `validate()` function before executing any query.

## Detection

- **ID:** `graphql-depth-limit`
- **Severity:** `low`
- **What to look for:** Enumerate every relevant item. For GraphQL APIs, check whether query depth limiting is implemented. This prevents deeply nested queries that could cause denial of service or expensive database operations.
- **Pass criteria:** At least 1 of the following conditions is met. A query depth limit is enforced (typically 5-10 levels). Queries exceeding the depth limit are rejected.
- **Fail criteria:** No query depth limit is implemented, allowing deeply nested queries.
- **Skip (N/A) when:** The application does not use GraphQL.
- **Detail on fail:** `"GraphQL has no query depth limit — attackers can craft deeply nested queries for DoS"`
- **Remediation:** Implement depth limiting using graphql-depth-limit or equivalent:

  ```ts
  import depthLimit from 'graphql-depth-limit'

  const server = new ApolloServer({
    schema,
    plugins: {
      didResolveOperation: (ctx) => {
        const { request: { query } } = ctx
        const depth = getQueryDepth(query)
        if (depth > 10) {
          throw new Error('Query depth exceeds limit')
        }
      }
    }
  })
  ```

## External references

- cwe CWE-400
- cwe CWE-1088
- owasp API4

Taxons: cost-efficiency, injection-and-input-trust

HTML version: https://auditbuffet.com/patterns/ab-000393
