← All casesConfidential · Anonymized
Case
#022
Developer Platform · Severity: Medium-High

GraphQL Depth & Cost Exhaustion

Unbounded GraphQL resolver fan-out enabled cheap client queries to consume disproportionate backend resources. Under adversarial or accidental patterns, the database connection pool saturated and downstream services experienced collateral degradation.

Industry
Developer Platform
Scope
API · GraphQL · Database
Timeline
R·Q1 → V·Q1 → R·Q2
Closed
Q2
01

Impact

DB pool saturation
95th-percentile pool wait: 30 ms → 1200 ms under crafted queries
Collateral impact
2 unrelated services shared the pool and experienced 502s
Cost of attack
Single client query, no auth escalation required
Impact vectors
  • Database pool saturation
  • Collateral service degradation
02

Reproduction

Steps below reproduce the finding against a staging replica. Where the reproduction affected a shared component, coordination was arranged before execution.

  1. 01Enumerate the schema via a low-privilege session (introspection partially restricted, sufficient signal remained).
  2. 02Compose a single query with nested pagination across 4 related types.
  3. 03Observe sustained backend DB pool saturation from a single connection.
03

Vulnerability

Resolver contract (simplified)graphql
type Organization {
  id: ID!
  members(first: Int = 100): [Member!]!
}
type Member {
  id: ID!
  projects(first: Int = 100): [Project!]!
}
type Project {
  id: ID!
  events(first: Int = 100): [Event!]!
}
# no depth limit, no cost analysis, no per-request budget
04

Mitigation

Client-side mitigation shipped and validated during the engagement. Reference patch below.

Depth + cost gate shippedjavascript
import { costAnalysis } from '@escape.tech/graphql-armor-cost-limit';
import depthLimit from 'graphql-depth-limit';

const server = new ApolloServer({
  schema,
  validationRules: [
    depthLimit(6),
    costAnalysis({
      maxCost: 1500,
      objectCost: 1,
      scalarCost: 0,
      depthCostFactor: 1.6,
    }),
  ],
});
05

Retest & Verify

  • Crafted queries now rejected with a cost-limit error before execution.
  • DB pool wait returned to baseline under identical workload.
  • Analytics read replica introduced for large-scan queries; no cross-service impact observed.
06

Deliverables

  • Technical Report
  • Query cost model
  • Depth-limit and cost-analysis patch
  • Retesting report
07

Sign-off

Handled by
Epulyx
Reviewed by
Ben Payer
Closed
Case closed after cost-model rollout validation.
Cookies

We use a minimal set of cookies to keep this site functional. Analytics cookies only with your consent. Cookie Policy.