Graphql Introspection in Feathersjs with Api Keys
Graphql Introspection in Feathersjs with Api Keys — how this specific combination creates or exposes the vulnerability
GraphQL introspection in FeathersJS allows clients to query the schema for types, queries, and mutations. When API keys are used for authorization but introspection is left enabled and publicly accessible, the API key does not prevent schema discovery. An unauthenticated attacker can send an introspection query to the GraphQL endpoint and learn the full shape of the API, including fields, relationships, and operations that may accept or return sensitive data. This exposure becomes a vulnerability because the API key is typically intended to control access to data and operations, not to gate the schema itself. If the GraphQL endpoint is reachable without requiring an API key for introspection, an attacker can use the schema to design more targeted attacks, such as BOLA/IDOR or property-level authorization flaws.
In FeathersJS, GraphQL hooks and services are often configured without explicit checks for introspection. API keys may be validated in a hook, but if that hook does not block introspection queries, the key provides no protection against schema discovery. Common misconfigurations include allowing introspection on production endpoints, failing to disable it in production mode, or not scoping introspection to authenticated and authorized contexts. Because FeathersJS integrates with GraphQL via adapters like feathers-graphql, the framework does not inherently disable introspection; it must be explicitly configured. Attackers can send standard introspection queries over HTTP POST with a valid or missing API key and still obtain a detailed schema, which can include sensitive types such as User, Token, or custom business entities.
Real-world examples include endpoints that respond to the __schema and __type queries without authentication. Even when API keys are required for data operations, introspection can remain open, creating an information leakage path that precedes further exploitation. This is especially risky when combined with other issues such as insufficient input validation or missing rate limiting, as attackers can probe the schema at scale. The combination of open introspection and API key usage gives a false sense of security: the key protects data operations but does nothing to hide the API structure. Using middleBrick’s LLM/AI Security checks and unauthenticated scanning, such misconfigurations are detectable through active probes and schema exposure tests, helping teams identify unintentional schema disclosure before it is exploited.
Api Keys-Specific Remediation in Feathersjs — concrete code fixes
To remediate GraphQL introspection exposure when using API keys in FeathersJS, disable introspection on production builds and enforce API key validation before schema resolution. You can configure the GraphQL provider to disable introspection or conditionally enable it only for trusted clients. Below are concrete examples showing how to set up API key validation and disable introspection in a FeathersJS GraphQL service.
Example 1: Disable introspection in production via GraphQL server options
const { GraphQLServer } = require('graphql-yoga');
const feathers = require('@feathersjs/feathers');
const graphql = require('@feathersjs/graphql');
const app = feathers();
const server = new GraphQLServer({
typeDefs: './schema.graphql',
resolvers: {
Query: {
// resolvers
}
},
introspection: process.env.NODE_ENV !== 'production', // disable in production
plugins: []
});
app.use('/graphql', graphql(server));
Example 2: API key validation hook that blocks introspection queries
// src/hooks/api-key-introspection.js
module.exports = function () {
return async context => {
const { params } = context;
const headers = params.headers || {};
const apiKey = headers['x-api-key'];
// Reject requests without an API key
if (!apiKey) {
throw new Error('Unauthorized: Missing API key');
}
// Validate API key (replace with your lookup logic)
const validKey = await validateApiKey(apiKey);
if (!validKey) {
throw new Error('Unauthorized: Invalid API key');
}
// Block introspection operations unless explicitly allowed
const query = params.query || {};
const operationName = query.operationName || query.__operation || 'query';
if (operationName === 'IntrospectionQuery') {
throw new Error('Forbidden: Introspection is not allowed');
}
return context;
};
};
async function validateApiKey(key) {
// Example validation against a store or environment variable
const validKeys = new Set([process.env.API_KEY_1, process.env.API_KEY_2]);
return validKeys.has(key);
}
Example 3: Apply the hook to a FeathersJS GraphQL service
const app = require('feathers')();
const express = require('@feathersjs/express');
const graphql = require('@feathersjs/graphql');
const apiKeyHook = require('./hooks/api-key-introspection');
app.configure(express.rest());
app.use('/graphql', graphql({
graphiql: false, // disable GraphiUI in production
playground: false,
// Pass hooks to the GraphQL layer
hooks: {
before: [apiKeyHook()]
}
}));
These examples ensure that API keys are required for all GraphQL operations and that introspection is disabled or restricted in production. You can further tighten controls by scoping introspection to specific roles or IPs using middleware conditions. middleBrick’s CLI and Dashboard can help verify that introspection is no longer exposed by scanning the endpoint with and without valid API keys, confirming that schema details are not leaked.
Related CWEs: dataExposure
| CWE ID | Name | Severity |
|---|---|---|
| CWE-200 | Exposure of Sensitive Information | HIGH |
| CWE-209 | Error Information Disclosure | MEDIUM |
| CWE-213 | Exposure of Sensitive Information Due to Incompatible Policies | HIGH |
| CWE-215 | Insertion of Sensitive Information Into Debugging Code | MEDIUM |
| CWE-312 | Cleartext Storage of Sensitive Information | HIGH |
| CWE-359 | Exposure of Private Personal Information (PII) | HIGH |
| CWE-522 | Insufficiently Protected Credentials | CRITICAL |
| CWE-532 | Insertion of Sensitive Information into Log File | MEDIUM |
| CWE-538 | Insertion of Sensitive Information into Externally-Accessible File | HIGH |
| CWE-540 | Inclusion of Sensitive Information in Source Code | HIGH |