HIGH graphql introspectionexpressbearer tokens

Graphql Introspection in Express with Bearer Tokens

Graphql Introspection in Express with Bearer Tokens — how this specific combination creates or exposes the vulnerability

GraphQL introspection is a schema-discovery feature that allows clients to query the type system for available queries, mutations, and types. When an Express server exposes a GraphQL endpoint without restricting introspection and also uses Bearer token authentication, the combination can unintentionally expose metadata that aids attackers even when authentication is required.

In this setup, the server accepts HTTP requests with an Authorization header containing a Bearer token, but introspection queries do not enforce the same authorization checks as regular operations. If the GraphQL handler applies introspection filtering inconsistently—allowing introspection regardless of token validity or scope—an unauthenticated or low-privilege client can still retrieve the full schema. This reveals sensitive data modeling choices, relationships, and potentially hints at internal business logic that should remain private.

For example, an attacker can send a POST request with a missing or invalid Bearer token and still receive a 200 response with schema details if introspection is enabled. The presence of a Bearer token requirement on some routes but not consistently on introspection creates an authorization bypass vector. Attackers can use this to map the API surface, identify hidden fields, and craft further attacks such as BOLA/IDOR or Property Authorization issues.

When combined with other checks run by middleBrick—such as Authentication, BOLA/IDOR, and Property Authorization—this misconfiguration is detectable. middleBrick scans the unauthenticated attack surface and can flag introspection exposure even when Bearer tokens are present but not uniformly enforced, providing prioritized findings with severity and remediation guidance.

Using the OpenAPI/Swagger spec analysis feature, middleBrick cross-references spec definitions with runtime behavior. If the spec documents introspection under security schemes but runtime responses leak schema data without proper token validation, the scan will highlight the inconsistency.

Bearer Tokens-Specific Remediation in Express — concrete code fixes

To secure GraphQL introspection in Express when using Bearer tokens, enforce authorization checks before allowing introspection queries. Below are concrete code examples demonstrating how to implement this correctly.

1. Middleware to validate Bearer tokens

Use an Express middleware that verifies the presence and validity of a Bearer token. This example uses a simple bearer-token check against a known value; in production, integrate with your identity provider or token verification library.

const jwt = require('jsonwebtoken');

function verifyBearerToken(req, res, next) {
  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'Unauthorized: missing Bearer token' });
  }
  const token = authHeader.split(' ')[1];
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = decoded;
    return next();
  } catch (err) {
    return res.status(401).json({ error: 'Unauthorized: invalid token' });
  }
}

2. Apply token verification to GraphQL endpoint

Apply the token verification middleware to the GraphQL route. This ensures that introspection and all other operations require a valid Bearer token.

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

const app = express();

app.use('/api/graphql', verifyBearerToken, graphqlHTTP((req, res, graphQLParams) => ({
  schema,
  graphiql: false,
  // Explicitly disable introspection for unauthorized requests
  customFormatErrorFn: (error) => ({
    message: error.message,
    code: error.extensions?.code || 'INTERNAL_SERVER_ERROR',
  }),
})));

app.listen(3000, () => console.log('Server running on port 3000'));

3. Disable introspection conditionally

You can further tighten security by disabling introspection entirely for production or allowing it only for specific trusted roles. The example below disables introspection unless a special scope is present in the token.

function introspectionAllowed(req) {
  return req.user && req.user.scopes && req.user.scopes.includes('schema:read');
}

app.use('/api/graphql', verifyBearerToken, graphqlHTTP((req, res, graphQLParams) => ({
  schema,
  graphiql: false,
  customFormatErrorFn: (error) => ({
    message: error.message,
    code: error.extensions?.code || 'INTERNAL_SERVER_ERROR',
  }),
  // Disable introspection unless authorized
  customResolverMiddleware: (next) => (root, args, context, info) => {
    const isIntrospection = info.fieldName === '__schema' || info.fieldName === '__type';
    if (isIntrospection && !introspectionAllowed(context.req)) {
      throw new Error('Introspection is not allowed');
    }
    return next(root, args, context, info);
  },
})));

4. Validate and log suspicious requests

Log introspection attempts that lack proper authorization to detect reconnaissance activity. Combine this with rate limiting to mitigate abuse.

app.use('/api/graphql', verifyBearerToken, (req, res, next) => {
  const graphQLParams = req.body;
  if (graphQLParams && graphQLParams.query && graphQLParams.query.includes('__schema')) {
    if (!introspectionAllowed(req)) {
      console.warn(`Introspection attempt without proper scope from ${req.ip}`);
    }
  }
  next();
}, graphqlHTTP(/* same as above */));

By applying these patterns, Express services that use Bearer tokens can prevent unauthorized schema exposure while maintaining usability for authenticated clients. These measures align with checks performed by middleBrick, such as Authentication, BOLA/IDOR, and Property Authorization, and help ensure that introspection is appropriately gated.

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

Can an attacker retrieve the GraphQL schema if introspection is disabled but authentication is required?
If introspection is properly disabled and authentication is enforced consistently on the endpoint, an attacker cannot retrieve the schema without valid credentials. Ensure middleware validates Bearer tokens for all requests and does not allow introspection for unauthorized or token-less calls.
How does middleBrick detect GraphQL introspection exposure when Bearer tokens are used?
middleBrick scans the unauthenticated attack surface and tests introspection endpoints regardless of token presence. It cross-references OpenAPI/Swagger spec definitions with runtime behavior to identify inconsistencies where introspection is allowed without proper authorization checks.