HIGH injection flawsfiberfirestore

Injection Flaws in Fiber with Firestore

Injection Flaws in Fiber with Firestore — how this combination creates or exposes the vulnerability

Injection flaws in a Fiber API that uses Google Cloud Firestore typically arise when request inputs are used to construct queries, document paths, or Firestore field filters without validation or sanitization. Because Firestore queries accept dynamic values, concatenating user-controlled data into collection names, document IDs, or query constraints can expose the application to unintended data access or behavior that is not directly a Firestore injection but is a logic flaw in how the API builds and executes operations.

In a Fiber-based service, route parameters, query strings, and JSON bodies may be bound directly into Firestore operations. For example, using c.Params to interpolate a document ID or collection segment without validation can lead to accessing or modifying data outside the intended scope. If the API dynamically builds a Firestore collection reference such as client.Collection(c.Params("collection")), an attacker could traverse to sensitive collections. Similarly, constructing field filters by string concatenation, such as firestore.Where("uid", "==", userInput), may bypass intended scoping if userInput is not treated as a value but inadvertently alters query structure.

Although Firestore does not support traditional SQL-like injection, the risk in Fiber arises from improper handling of inputs that affect which documents are read or written. An attacker might supply crafted IDs to access other users’ data (a Broken Object Level Authorization issue), or use specially formatted values to trigger unexpected behavior in the application layer. Because Firestore operations are often chained with application logic, an injection-style flaw can lead to mass data exposure or unauthorized mutations across user boundaries.

In the context of middleBrick’s 12 security checks, Injection Flaws are assessed alongside BOLA/IDOR and Input Validation. The scanner tests whether unauthenticated endpoints reflect or execute unsafe patterns by probing dynamic endpoints that incorporate user input into Firestore operations. Real-world examples include CVE-adjacent patterns where predictable document IDs or unescaped query values allow enumeration or unauthorized access across tenant boundaries.

When using the OpenAPI/Swagger spec analysis feature, middleBrick cross-references spec definitions with runtime findings to highlight endpoints where parameters are passed into Firestore operations without adequate constraints. This helps identify cases where path or query parameters are used to form collection or document references dynamically, which is a common precursor to injection-related logic flaws.

Firestore-Specific Remediation in Fiber — concrete code fixes

To remediate injection-related risks in Fiber applications using Firestore, validate and sanitize all external inputs before using them to build Firestore queries or references. Use strongly typed parameters and avoid string interpolation for collection names or document IDs. Prefer constant or enumerated values for collections and enforce strict ID formats using validation libraries.

Below are concrete code examples for secure Fiber handlers.

Secure Document Access by Known ID

Instead of using raw user input as a document ID, validate it against an allowlist or regex and use it to fetch a specific document within a predefined collection:

package main

import (
	"context"
	"fmt"
	"github.com/gofiber/fiber/v2"
	"github.com/google/uuid"
	"cloud.google.com/go/firestore"
)

func getDocument(c *fiber.Ctx) error {
	ctx := c.Context()
	docID := c.Params("id")
	// Validate document ID format
	if _, err := uuid.Parse(docID); err != nil {
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid document ID"})
	}
	client, err := firestore.NewClient(ctx, <your-project-id>)
	if err != nil {
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "failed to create client"})
	}
	defer client.Close()
	docRef := client.Collection("user_profiles").Doc(docID)
	snap, err := docRef.Get(ctx)
	if err != nil {
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "failed to fetch document"})
	}
	if !snap.Exists() {
		return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "not found"})
	}
	return c.JSON(snap.Data())
}

Dynamic Collection Name with Allowlist

If your application must use dynamic collections, validate the collection name against a strict allowlist before creating a reference:

func getFromDynamicCollection(c *fiber.Ctx) error {
	ctx := c.Context()
	collectionName := c.Params("collection")
	allowedCollections := map[string]bool{"public_posts": true, "audit_logs": true}
	if !allowedCollections[collectionName] {
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid collection name"})
	}
	client, err := firestore.NewClient(ctx, <your-project-id>)
	if err != nil {
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "failed to create client"})
	}
	defer client.Close()
	docs, err := client.Collection(collectionName).Where("published", "==", true).Documents(ctx).GetAll()
	if err != nil {
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "failed to query collection"})
	}
	var results []interface{}
	for _, doc := range docs {
		results = append(results, doc.Data())
	}
	return c.JSON(results)
}

Parameterized Queries with Input Validation

When querying with user-supplied values, treat them strictly as values in filters, not as part of the query structure:

func searchUsers(c *fiber.Ctx) error {
	ctx := c.Context()
	email := c.Query("email")
	// Basic format validation
	if email == "" || !strings.Contains(email, "@") {
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid email"})
	}
	client, err := firestore.NewClient(ctx, <your-project-id>)
	if err != nil {
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "failed to create client"})
	}
	defer client.Close()
	iter := client.Collection("users").Where("email", "==", email).Documents(ctx)
	defer iter.Stop()
	var matches []interface{}
	for {
		doc, err := iter.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "query failed"})
		}
		matches = append(matches, doc.Data())
	}
	return c.JSON(matches)
}

By enforcing strict input validation and avoiding dynamic construction of collection and document identifiers, you reduce the risk of injection-style flaws in Fiber applications that use Firestore. These practices align with secure coding guidance and help ensure that unauthenticated attack surface testing, as performed by middleBrick, reveals fewer critical findings.

Frequently Asked Questions

Can Firestore operations in Fiber lead to IDOR even without direct injection?
Yes. If endpoints use user input to build Firestore document references without proper authorization checks, attackers may manipulate IDs to access other users’ data, resulting in BOLA/IDOR findings that middleBrick detects during unauthenticated scans.
Does middleBrick’s LLM/AI Security testing apply to Firestore APIs?
middleBrick’s LLM/AI Security checks focus on endpoints that expose AI model interactions, such as unauthenticated LLM endpoints. Firestore APIs are not AI models, so those specific probes do not apply; however, standard injection and input validation checks still assess Firestore-related endpoints.