HIGH graphql introspectionfeathersjsjwt tokens

Graphql Introspection in Feathersjs with Jwt Tokens

Graphql Introspection in Feathersjs with Jwt Tokens — how this specific combination creates or exposes the vulnerability

GraphQL introspection is a built-in feature that allows clients to query the schema structure, types, and operations of a GraphQL API. In FeathersJS, GraphQL support is commonly added through integrations such as feathers-graphql or adapters that expose a GraphQL endpoint. When authentication is handled via JWT tokens but introspection is left enabled and unprotected, the combination creates a significant information disclosure risk.

In this setup, unauthenticated or partially authenticated requests can still reach the GraphQL endpoint because JWT validation may be applied only to specific resolvers or services, not to the introspection query itself. An attacker can send an introspection query over HTTPS to the FeathersJS GraphQL endpoint and retrieve the full schema, including queries, mutations, subscriptions, and the shape of underlying data models. This reveals sensitive implementation details such as field names, relationships, and potentially deprecated operations that can be leveraged for further attacks.

Because JWT tokens are often used to convey user roles and permissions, developers may assume that introspection is safe behind authentication. However, if the GraphQL server does not explicitly disable introspection for non-authenticated requests, or if a valid JWT token is obtained through other means (e.g., leaked credentials or insecure storage), the attacker gains insight into the API surface without needing valid user credentials. This is particularly dangerous in environments where the GraphQL endpoint is exposed broadly, such as in public-facing services or misconfigured staging environments.

Moreover, FeathersJS applications that use JWT tokens typically rely on hooks for authentication and validation. If introspection is not explicitly blocked in the GraphQL layer before hook execution, the server still processes the query, consuming resources and logging activity. This can aid in reconnaissance for more targeted attacks, such as BOLA/IDOR or privilege escalation, by mapping which operations are available and what data shapes they return.

Real-world examples include services where the GraphQL endpoint follows a predictable path like /graphql. An attacker can use a simple curl command to perform introspection even when JWT protection is present but not uniformly enforced. The returned schema may include sensitive types such as User, Token, or internal relations that should never be exposed. This information directly supports further exploitation, aligning with OWASP API Top 10 categories such as Broken Object Level Authorization and Excessive Data Exposure.

Jwt Tokens-Specific Remediation in Feathersjs — concrete code fixes

To secure a FeathersJS GraphQL endpoint that uses JWT tokens, you must explicitly disable introspection for requests that lack valid authentication or are not explicitly authorized. Below are concrete remediation steps with code examples.

First, ensure that your GraphQL HTTP handler validates JWT tokens before allowing any query execution. In FeathersJS, this is typically done in a hook. The following example shows a JWT verification hook that attaches the decoded payload to the context:

// src/hooks/authentication.js
const { AuthenticationError } = require('@feathersjs/errors');
const jwt = require('jsonwebtoken');

module.exports = function authentication(options = {}) {
  return async context => {
    const { headers } = context.params;
    const token = headers && headers.authorization && headers.authorization.split(' ')[1];

    if (!token) {
      throw new AuthenticationError('Invalid access token');
    }

    try {
      const payload = jwt.verify(token, process.env.JWT_SECRET);
      context.params.user = payload;
    } catch (error) {
      throw new AuthenticationError('Invalid access token');
    }

    return context;
  };
};

Second, configure your GraphQL server to disable introspection when a valid JWT is not present. With feathers-graphql, you can customize the GraphQL HTTP handler options. The following example shows how to enable introspection only for requests that include a verified user in the context:

// src/app.js
const path = require('path');
const { express } = require('@feathersjs/express');
const { GraphQLServer } = require('feathers-graphql');
const authentication = require('./hooks/authentication');

const app = express();

const graphqlServer = new GraphQLServer({
  path: '/graphql',
  graphqlOptions: {
    schema: require('./schema'),
    graphiql: false,
    introspection: false, // disable by default
    context: async ({ req }) => {
      // The authentication hook will have already set req.user if valid
      return {
        user: req.user || null
      };
    }
  }
});

// Override the handler to allow introspection only for authenticated requests
const originalHandler = graphqlServer.app;
graphqlServer.app = (req, res, next) =>
```

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

How can I safely enable introspection for trusted clients in a FeathersJS GraphQL API using JWT tokens?
Disable introspection globally, then create a separate GraphQL endpoint or middleware that enables introspection only when a valid JWT token with specific roles (e.g., admin) is present. Validate the token before allowing introspection.
What is the risk of leaving GraphQL introspection enabled in a FeathersJS app protected by JWT tokens?
An attacker can retrieve the full schema and understand data models, queries, and mutations, which facilitates targeted attacks such as BOLA/IDOR or privilege escalation, even when JWT tokens are required for other operations.