HIGH graphql introspectionexpress

Graphql Introspection in Express

How Graphql Introspection Manifests in Express

Graphql Introspection is a powerful feature that allows clients to query the schema of a GraphQL API, but when exposed in production, it becomes a significant security risk. In Express applications, this manifests when developers use the graphql-express middleware without properly configuring introspection settings.

The most common scenario occurs when developers initialize their GraphQL server like this:

const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const schema = require('./schema');

const app = express();

app.use('/graphql', graphqlHTTP({
  schema: schema,
  graphiql: true // Often left enabled in development
}));

By default, graphql-express enables introspection when graphiql is true or when no explicit introspection option is provided. This creates an attack vector where malicious actors can enumerate all types, queries, mutations, and subscriptions available in your API.

In Express applications, this vulnerability is particularly dangerous because:

  • The GraphQL endpoint is typically mounted at a predictable path like /graphql
  • Express's middleware stack doesn't provide any built-in protection
  • The introspection query can be sent via standard HTTP POST requests
  • Attackers can use the discovered schema to craft targeted exploits

A typical introspection attack payload looks like:

{
  "query": "{\n    __schema {\n      types {\n        name\n        fields {\n          name\n          type {\n            name\n            ofType {\n              name\n            }\n          }\n        }\n      }\n    }\n  }"
}

When sent to an unprotected Express GraphQL endpoint, this returns the complete schema, exposing all available operations, input types, and potential data structures. Attackers can then use this information to identify vulnerable mutations, sensitive queries, or misconfigured resolvers.

Express-specific implementations often compound this risk when developers use additional middleware like authentication or rate limiting after the GraphQL middleware, making it harder to globally disable introspection across all routes.

Express-Specific Detection

Detecting GraphQL introspection vulnerabilities in Express applications requires both manual testing and automated scanning. The most straightforward detection method is to send an introspection query to your GraphQL endpoint and observe the response.

Manual detection can be performed using curl:

curl -X POST http://your-express-app/graphql \
  -H "Content-Type: application/json" \
  -d '{"query": "{__schema {types {name}}"}'

If the server responds with schema information rather than an error or empty response, introspection is enabled.

For automated detection in Express applications, middleBrick provides comprehensive scanning that specifically tests for GraphQL introspection vulnerabilities. The scanner sends the standard introspection query to any GraphQL endpoint it discovers and analyzes the response for schema exposure.

middleBrick's detection approach includes:

  • Identifying GraphQL endpoints by analyzing request patterns and content types
  • Submitting the introspection query to test for enabled introspection
  • Analyzing the response structure to confirm schema exposure
  • Checking for GraphiQL or GraphQL Playground interfaces that might indicate development configurations
  • Scanning for common GraphQL endpoint paths like /graphql, /api/graphql, and custom paths

The scanner also examines OpenAPI specifications if provided, looking for GraphQL endpoints and their configuration. This is particularly useful for Express applications that use tools like swagger-ui-express alongside GraphQL.

Another detection method specific to Express is examining the middleware stack. If you're using express-graphql, check your initialization code for missing introspection: false options. The scanner can automatically detect when the GraphQL middleware is configured without proper security settings.

middleBrick's API security scanning takes approximately 5-15 seconds and provides a detailed report showing whether introspection is enabled, the specific GraphQL endpoints discovered, and the completeness of the exposed schema. The report includes severity ratings and specific remediation steps tailored to Express applications.

Express-Specific Remediation

Remediating GraphQL introspection vulnerabilities in Express requires proper configuration of the express-graphql middleware. The most direct fix is to explicitly disable introspection in production environments.

Here's the corrected Express configuration:

const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const schema = require('./schema');

const app = express();

const isProduction = process.env.NODE_ENV === 'production';

app.use('/graphql', graphqlHTTP({
  schema: schema,
  graphiql: !isProduction,
  introspection: !isProduction
}));

This configuration ensures that introspection and GraphiQL are only available in non-production environments. For production, both are disabled, preventing unauthorized schema discovery.

For more granular control, you can implement conditional middleware that checks authentication before enabling GraphQL features:

const graphqlMiddleware = graphqlHTTP({
  schema: schema,
  introspection: false
});

app.use('/graphql', (req, res, next) => {
  if (req.headers['x-internal-access'] === 'true') {
    return graphqlMiddleware(req, res, next);
  }
  next();
});

This approach allows internal tools to access the GraphQL API while blocking public introspection attempts.

Another Express-specific remediation involves using custom validation middleware before the GraphQL resolver:

const { graphql } = require('graphql');

app.use('/graphql', async (req, res) => {
  const { query, variables } = req.body;
  
  // Block introspection queries
  if (query && query.includes('__schema')) {
    return res.status(403).json({
      errors: [{ message: 'Introspection queries are not allowed' }]
    });
  }
  
  try {
    const result = await graphql(schema, query, null, {}, variables);
    res.json(result);
  } catch (error) {
    res.status(400).json({ errors: [error] });
  }
});

This manual approach gives you complete control over which queries are allowed, though it requires more maintenance than the built-in express-graphql options.

For Express applications using TypeScript or modern JavaScript, you can also implement compile-time checks:

import { GraphQLSchema } from 'graphql';

function createSecureGraphQLMiddleware(schema: GraphQLSchema) {
  return graphqlHTTP({
    schema,
    graphiql: false,
    introspection: false,
    customFormatErrorFn: (error) => ({
      message: error.message,
      locations: error.locations,
      path: error.path
    })
  });
}

middleBrick's scanning can verify these remediations by testing the GraphQL endpoint after implementation, ensuring that introspection queries are properly blocked and that the API remains functional for legitimate operations.

Related CWEs: dataExposure

CWE IDNameSeverity
CWE-200Exposure of Sensitive Information HIGH
CWE-209Error Information Disclosure MEDIUM
CWE-213Exposure of Sensitive Information Due to Incompatible Policies HIGH
CWE-215Insertion of Sensitive Information Into Debugging Code MEDIUM
CWE-312Cleartext Storage of Sensitive Information HIGH
CWE-359Exposure of Private Personal Information (PII) HIGH
CWE-522Insufficiently Protected Credentials CRITICAL
CWE-532Insertion of Sensitive Information into Log File MEDIUM
CWE-538Insertion of Sensitive Information into Externally-Accessible File HIGH
CWE-540Inclusion of Sensitive Information in Source Code HIGH

Frequently Asked Questions

Why is GraphQL introspection dangerous in production?
GraphQL introspection reveals your entire API schema, including all available queries, mutations, and types. This information helps attackers craft targeted exploits, discover sensitive data structures, and identify vulnerable operations. In production environments, this exposure significantly increases your attack surface and can lead to data breaches or unauthorized access.
Does disabling introspection break GraphQL clients?
No, disabling introspection doesn't break GraphQL clients. Introspection is only needed for development tools like GraphiQL, GraphQL Playground, or schema generation tools. Production GraphQL clients already have the schema they need, either bundled with the application or fetched during development. Disabling introspection simply prevents unauthorized schema discovery while maintaining full API functionality.