MEDIUM graphql introspectionfeathersjsfirestore

Graphql Introspection in Feathersjs with Firestore

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

GraphQL introspection is a feature that allows clients to query the schema for type information, which is invaluable for development tools but can expose sensitive design details in production. When using FeathersJS with a Firestore backend, introspection can reveal the structure of your service definitions, field types, and relationships that are otherwise abstracted by the ORM-like layer. This becomes a security concern when the introspection query is allowed through to the Firestore layer without restriction, potentially exposing data model details that aid an attacker in crafting targeted BOLA/IDOR or Property Authorization attacks.

In a FeathersJS application, GraphQL schemas are often defined as part of the service configuration. If introspection is enabled and the GraphQL endpoint is publicly reachable, an attacker can send an introspection query like { __schema { queryType { name } types { name fields { name } } } } and receive a full description of the available queries and mutations. Because FeathersJS may directly map these operations to Firestore collections and documents, the returned schema can hint at collection names, document IDs, and field hierarchies that map 1-to-1 with your Firestore database structure. This mapping is especially sensitive when Firestore security rules are misconfigured or when combined with weak authentication checks, as the exposed schema can guide an attacker toward endpoints where BOLA/IDOR vulnerabilities exist.

Additionally, because FeathersJS typically uses a service-oriented architecture, each GraphQL type often corresponds to a Firestore collection or a subcollection. Introspection can expose nested types and relations, revealing how documents are linked — for example, a posts type referencing a userId field that maps to a Firestore document in a users collection. If the API also lacks proper rate limiting or authentication on the GraphQL endpoint, this information can be leveraged in conjunction with other checks such as Unauthenticated LLM Endpoint detection or Property Authorization weaknesses. MiddleBrick scans detect such exposure as part of its 12 parallel security checks, highlighting GraphQL introspection as a finding when it reveals actionable attack surfaces in the context of Firestore-backed FeathersJS services.

Firestore-Specific Remediation in Feathersjs — concrete code fixes

To secure a FeathersJS application using Firestore, you should disable or guard GraphQL introspection in production and enforce strict input validation and authorization at the service layer. Below are concrete code examples that demonstrate how to configure a FeathersJS GraphQL service with Firestore while mitigating introspection-related risks.

1. Disable introspection in production

When initializing the GraphQL server, set introspection to false in production environments. This prevents external clients from querying the schema.

const { GraphQLServer } = require('graphql-yoga');
const feathers = require('@feathersjs/feathers');
const graphql = require('@feathersjs/graphql');

const app = feathers();

const server = new GraphQLServer({
  typeDefs: './src/schema.graphql',
  resolvers: require('./src/resolvers'),
  introspection: process.env.NODE_ENV !== 'production', // disable in prod
});

app.configure(graphql({ server }));

2. Secure Firestore service definitions

Define your FeathersJS Firestore service with explicit filtering and validation to ensure that only intended fields are exposed and that document access is restricted.

const { Service } = require('feathers-firebase');
const admin = require('firebase-admin');

admin.initializeApp({
  credential: admin.credential.applicationDefault(),
});

class FirestorePostsService extends Service {
  async get(id, params) {
    const doc = await admin.firestore().collection('posts').doc(id).get();
    if (!doc.exists) {
      throw new Error('Document not found');
    }
    // Ensure the requesting user has access, if applicable
    if (params.user && params.user.uid !== doc.data().userId) {
      throw new Error('Unauthorized');
    }
    return doc.data();
  }
}

app.use('/posts', new FirestorePostsService({
  Model: admin.firestore(),
  collection: 'posts',
  paginate: { default: 10, max: 50 },
}));

3. Apply field-level authorization

Use FeathersJS hooks to strip sensitive fields before returning data to the client, ensuring that even if introspection reveals a field, it cannot be accessed without proper permissions.

const { iff, isProvider } = require('feathers-hooks-common');

app.service('posts').hooks({
  after: {
    all: [
      iff(isProvider('external'), (context) => {
        const { userId } = context.result;
        delete context.data.passwordHash;
        if (context.result.__v) delete context.result.__v;
        // Ensure only safe fields are returned
        return context;
      }),
    ],
  },
});

4. Validate and limit GraphQL queries

Use schema directives or query whitelisting to prevent overly broad introspection or deeply nested queries that could traverse Firestore document trees unexpectedly.

// Example schema directive to block introspection in production
const { makeExecutableSchema } = require('@graphql-tools/schema');

const schema = makeExecutableSchema({
  typeDefs,
  resolvers,
  directiveResolvers: {
    disableInProduction: {
      Field: (_, args, ctx, info) => {
        if (process.env.NODE_ENV !== 'production' && info.schemaIntrospection) {
          throw new Error('Introspection is disabled in production');
        }
      },
    },
  },
});

By combining environment-aware introspection settings, strict Firestore document access patterns, and FeathersJS hooks, you reduce the attack surface exposed through GraphQL while still leveraging the flexibility of a NoSQL backend.

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 disabling GraphQL introspection break development workflows?
Yes, disabling introspection in production can affect tools like GraphiQL or Apollo Studio that rely on it for auto-documentation. Use it only in production and keep it enabled in development environments.
Does MiddleBrick detect GraphQL introspection exposure in FeathersJS services?
Yes, MiddleBrick runs parallel security checks including GraphQL introspection analysis. If your FeathersJS + Firestore API exposes schema details in production, it will be reported with severity and remediation guidance.