HIGH graphql introspectionfirestore

Graphql Introspection in Firestore

How Graphql Introspection Manifests in Firestore

GraphQL introspection in Firestore contexts typically emerges through misconfigured Apollo Server or similar GraphQL libraries deployed alongside Firestore databases. When developers enable introspection in production environments, attackers can map the entire GraphQL schema, revealing field names, types, resolvers, and potentially sensitive data structures that map directly to Firestore collections and documents.

The most common Firestore-specific manifestation occurs when GraphQL resolvers directly expose Firestore collections without proper access controls. For example, a resolver might query an entire collection:

const resolvers = {
  Query: {
    users: async () => {
      const snapshot = await firestore.collection('users').get();
      return snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
    }
  }
};

When introspection is enabled, an attacker can discover this users query and understand it returns all user documents. They can then use tools like GraphQL Playground or Insomnia to enumerate all fields, potentially exposing sensitive user data stored in Firestore.

Another Firestore-specific pattern involves nested queries that traverse document references. Consider a GraphQL schema where users have orders, and orders reference Firestore documents:

const resolvers = {
  User: {
    orders: async (parent) => {
      const snapshot = await firestore.collection('orders')
        .where('userId', '==', parent.id)
        .get();
      return snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
    }
  },
  Order: {
    items: async (parent) => {
      const snapshot = await firestore.collection('orderItems')
        .where('orderId', '==', parent.id)
        .get();
      return snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
    }
  }
};

With introspection enabled, attackers can discover these relationships and craft queries that traverse the entire data graph, potentially accessing data they shouldn't see through legitimate GraphQL queries that map to Firestore document relationships.

Firestore-Specific Detection

Detecting GraphQL introspection vulnerabilities in Firestore environments requires both automated scanning and manual verification. The middleBrick API security scanner specifically tests for this by attempting GraphQL introspection queries against detected endpoints. When middleBrick identifies a GraphQL endpoint, it sends the standard introspection query:

query IntrospectionQuery {
  __schema {
    types {
      kind
      name
      fields {
        name
        args {
          name
          type {
            name
            kind
          }
        }
      }
    }
  }
}

For Firestore-specific detection, middleBrick analyzes the schema structure to identify patterns that suggest Firestore integration. This includes detecting queries that follow Firestore collection naming conventions, resolvers that use Firestore SDK patterns, and field structures that map to Firestore document schemas.

Manual detection involves examining GraphQL endpoints for the presence of introspection queries. Using tools like curl or GraphQL clients, you can test:

curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"query": "query { __schema { types { name } } }"}' \
  https://your-api.com/graphql

If this returns a complete schema, introspection is enabled. For Firestore-specific analysis, examine the returned types for patterns like:

  • Collection names matching Firestore conventions (plural nouns)
  • Fields that suggest document references (fields ending with Id)
  • Query patterns that imply Firestore queries (pagination arguments like first, offset)

middleBrick goes further by analyzing the actual runtime behavior. It attempts to execute queries that would be particularly revealing for Firestore-backed APIs, such as queries that might return entire collections or traverse document relationships that suggest Firestore's document reference system.

Firestore-Specific Remediation

Remediating GraphQL introspection vulnerabilities in Firestore environments requires a multi-layered approach. The first and most critical step is disabling introspection in production environments. With Apollo Server, this is straightforward:

const server = new ApolloServer({
  typeDefs,
  resolvers,
  introspection: process.env.NODE_ENV === 'development',
  playground: process.env.NODE_ENV === 'development'
});

For Firestore-specific security, implement proper authorization at the resolver level using Firebase Admin SDK's security features. Instead of exposing entire collections, implement field-level security:

const resolvers = {
  Query: {
    user: async (_, { id }, context) => {
      // Verify the requesting user has access to this document
      if (!context.user || context.user.uid !== id) {
        throw new Error('Unauthorized');
      }
      
      const doc = await firestore.collection('users').doc(id).get();
      if (!doc.exists) throw new Error('Not found');
      return { id: doc.id, ...doc.data() };
    }
  },
  User: {
    orders: async (parent, _, context) => {
      // Only return orders belonging to the requesting user
      const snapshot = await firestore.collection('orders')
        .where('userId', '==', parent.id)
        .where('ownerId', '==', context.user.uid)
        .get();
      return snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
    }
  }
};

Implement Firestore security rules as a second layer of defense. Even if GraphQL introspection reveals schema information, Firestore security rules prevent unauthorized data access:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      allow read, write: if request.auth.uid == userId;
    }
    
    match /orders/{orderId} {
      allow read, write: if request.auth.uid == resource.data.ownerId;
    }
  }
}

For production environments, consider implementing custom directives that automatically apply authorization checks based on the authenticated user's permissions. This creates a consistent security layer across all resolvers:

const typeDefs = gql`
  directive @requireAuth on FIELD_DEFINITION
  
  type Query {
    user(id: ID!): User! @requireAuth
  }
`;

const server = new ApolloServer({
  typeDefs,
  resolvers,
  schemaTransforms: [
    transformSchema(({ schema }) => {
      const authDirective = schema.getDirective('requireAuth');
      return mapSchema(schema, {
        transformField: (fieldConfig, context) => {
          if (fieldConfig.astNode?.directives?.some(d => d.name.value === 'requireAuth')) {
            return {
              ...fieldConfig,
              resolve: async (root, args, context, info) => {
                if (!context.user) throw new Error('Unauthorized');
                return fieldConfig.resolve(root, args, context, info);
              }
            };
          }
          return fieldConfig;
        }
      });
    })
  ]
});

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 does GraphQL introspection differ from Firestore security rules?
GraphQL introspection reveals the schema structure and available queries, while Firestore security rules control actual data access at the database level. Introspection is about what queries you can make; security rules are about what data you can access. Both are important: disable introspection in production to prevent schema discovery, and implement strong Firestore security rules to prevent unauthorized data access even if the schema is known.
Can middleBrick detect GraphQL introspection in Firestore APIs?
Yes, middleBrick specifically tests for GraphQL introspection by sending standard introspection queries to detected GraphQL endpoints. For Firestore-specific detection, it analyzes the schema structure and runtime behavior to identify patterns that suggest Firestore integration, such as collection naming conventions and document reference patterns. The scanner provides a security score with findings that include whether introspection is enabled and what data exposure risks exist.