Security Resources

⌘K
  1. Home
  2. Security Resources
  3. Secure Code Explain
  4. GraphQL Introspection and Query Depth Abuse

GraphQL Introspection and Query Depth Abuse

Here is an example of Node.js code that is vulnerable to GraphQL introspection and query depth abuse:

🥺 Vulnerable Code

// Vulnerable: full schema exposed, unlimited query depth and cost
const server = new ApolloServer({
  typeDefs,
  resolvers,
  introspection: true,
});

// An attacker can then run:
// { users { posts { author { posts { author { posts { title } } } } } } }

Introspection hands over the complete schema, including the internal mutations and fields that never appear in the public client. With that map, a deeply nested or aliased query multiplies into millions of resolver calls and database round trips, so one HTTP request takes the API down. Aliases and batched operations also turn a single request into thousands of login or lookup attempts, which walks straight past a per-request rate limit.

😎 Secure Code

Here is a version of the same code that is secured against GraphQL introspection and query depth abuse:

const depthLimit = require("graphql-depth-limit");
const { createComplexityLimitRule } = require("graphql-validation-complexity");

const isProd = process.env.NODE_ENV === "production";

const server = new ApolloServer({
  typeDefs,
  resolvers,
  introspection: !isProd,
  validationRules: [
    depthLimit(7),
    createComplexityLimitRule(1000),
  ],
  allowBatchedHttpRequests: false,
  formatError: (error) => ({
    message: isProd ? "Request failed" : error.message,
  }),
});

Introspection and the playground are development conveniences, so they are off in production, and the depth and complexity rules reject an abusive document before a single resolver runs. Turning off HTTP batching removes the alias-and-batch brute force trick. None of this replaces authorization: check permissions inside each resolver against the authenticated user, because hiding a field from the schema is not the same as protecting the data behind it.