HIGH graphql introspectionfiberfirestore

Graphql Introspection in Fiber with Firestore

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

GraphQL introspection allows clients to query the schema for types, queries, and mutations. In a Fiber-based API that uses Firestore as the backend data source, enabling introspection without access controls exposes structural details that can aid an attacker. Because introspection is part of the GraphQL specification, many servers ship with it enabled in development and forget to disable it in production.

When a Fiber GraphQL endpoint backed by Firestore responds to an introspection query, it may return full type definitions, including custom scalars, argument descriptions, and resolver signatures. If the resolver logic or Firestore field paths are reflected in the schema (for example, via argument names or directives), an attacker gains insight into how data is modeled and accessed. This can reveal sensitive document structures, collection names, and potential query patterns that map to Firestore security rules weaknesses.

In a black-box scan, middleBrick runs the GraphQL introspection query as one of its 12 parallel security checks. If the endpoint returns a 200 with schema details, the finding is reported with severity and guidance. The scan does not rely on internal architecture; it only observes behavior. A vulnerable endpoint might return a payload like the following simplified example when queried with __schema:

{ __schema { queryType { name } types { name fields { name } } } }

Even when authentication is required at the HTTP layer, if the GraphQL endpoint also exposes introspection, unauthenticated attackers can still learn about operations that may be reachable via other vectors. The risk is compounded when the API uses predictable query names tied to Firestore collections, making automated enumeration feasible. middleBrick’s BOLA/IDOR and Property Authorization checks may surface additional findings that indicate whether introspection-derived knowledge can be leveraged to traverse relationships or bypass intended authorization assumptions.

Because Fiber is a fast, minimalist web framework for Go, developers sometimes overlook middleware ordering. If a GraphQL handler is mounted without proper middleware to reject introspection before routing to the resolver, the endpoint remains exposed. Coupled with Firestore’s flexible document model, this can inadvertently disclose collection hierarchies and field usage patterns that should remain internal.

Firestore-Specific Remediation in Fiber — concrete code fixes

To mitigate GraphQL introspection risks in a Fiber application using Firestore, control access to the GraphQL endpoint and limit what the server reveals. The most straightforward remediation is to disable introspection entirely unless it is explicitly required for tooling, and to enforce it only in trusted environments.

Below is an example of a Fiber GraphQL server using graphql-go with introspection disabled in production. The server connects to Firestore to resolve a simple document query, but the GraphQL handler is configured to reject introspection operations before they reach the resolver:

import (
    "context"
    "github.com/gofiber/fiber/v2"
    "github.com/graph-gophers/graphql-go"
    "github.com/graph-gophers/graphql-go/relay"
    "cloud.google.com/go/firestore"
)

type DocumentResolver struct {
    firestoreClient *firestore.Client
}

func (r *DocumentResolver) Documents() ([]*Document, error) {
    ctx := context.Background()
    iter := r.firestoreClient.Collection("documents").Documents(ctx)
    defer iter.Stop()
    var docs []*Document
    for {
        doc, err := iter.Next()
        if err != nil {
            return nil, err
        }
        var d Document
        if err := doc.DataTo(&d); err != nil {
            return nil, err
        }
        docs = append(docs, &d)
    }
}

type Document struct {
    ID   string
    Name string
}

func main() {
    ctx := context.Background()
    fsClient, err := firestore.NewClient(ctx, "your-project-id")
    if err != nil {
        panic(err)
    }
    defer fsClient.Close()

    schema := graphql.MustParseSchema(`
        type Document { id: ID!, name: String! }
        type Query { documents: [Document] }
        schema {
            query: Query
        }
    `, &DocumentResolver{firestoreClient: fsClient})

    app := fiber.New()
    app.Post("/graphql", func(c *fiber.Ctx) error {
        var req struct {
            Query string `json:"query"`
        }
        if err := c.BodyParser(&req); err != nil {
            return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid request"})
        }
        // Explicitly block introspection unless in a controlled context
        if !isIntrospectionAllowed(c) && isIntrospectionQuery(req.Query) {
            return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "introspection disabled"})
        }
        gqlReq := graphql.Request{Query: req.Query}
        var resp graphql.Response
        schema.Exec(&resp, graphql.Params{Context: c.Context(), Request: &gqlReq})
        return c.JSON(resp)
    })
    app.Listen(":3000")
}

func isIntrospectionQuery(query string) bool {
    // naive detection for example; use a proper parser in production
    return query != "" && (query == "__schema { __typename }" || (len(query) > 9 && query[:9] == "__schema"))
}

func isIntrospectionAllowed(c *fiber.Ctx) bool {
    // allow introspection only from internal tooling IPs or authenticated admin sessions
    return false
}

In this setup, introspection is blocked at the handler level, so even if a client sends an introspection query, the server returns a 403. This reduces the attack surface without requiring changes to Firestore security rules. For environments where introspection must be available (e.g., for GraphQL playgrounds), restrict access via network policies, API keys, or mutual TLS, and ensure findings from middleBrick’s Authentication and Property Authorization checks are reviewed to confirm that introspection does not leak resolver-specific details.

Additionally, validate and sanitize inputs that feed into Firestore queries to mitigate injection risks. Even though Firestore uses parameterized lookups, ensure that user-controlled values are not used to dynamically construct collection or document paths that could bypass intended rules. middleBrick’s Input Validation and Data Exposure checks can surface areas where user-supplied data influences query construction.

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

What should I do if middleBrick reports a GraphQL introspection finding on my Fiber + Firestore API?
Disable introspection in production unless it is required for tooling, and restrict access to introspection endpoints using network controls or authentication. Review the specific schema details exposed and ensure Firestore security rules do not rely on obscurity.
Can introspection alone lead to data exposure in Firestore?
Introspection does not directly read data, but it can reveal collection names, field types, and query patterns that may help an attacker craft probes. Combine introspection restrictions with strong Firestore rules and avoid reflecting sensitive field names in GraphQL schema descriptions.