HIGH injection flawschifirestore

Injection Flaws in Chi with Firestore

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

Injection flaws in server-side rendered applications using Chi and Firestore typically arise when dynamic values from HTTP requests are interpolated into Firestore operations without proper validation or escaping. Chi is a lightweight router for Go, and when route parameters, query strings, or headers are used to construct Firestore keys, collection names, or query constraints, an attacker can inject unexpected values that alter the intended data access patterns.

For example, using a user-supplied ID directly as a document path component can lead to Insecure Direct Object References (IDOR) or access to unrelated documents. If a route like /users/{userID}/profile uses chi.URLParam(r, "userID") to form a Firestore document reference such as client.Collection("users").Doc(userID).Get(ctx), an attacker can manipulate userID to reference admin or system documents by supplying values like ../settings or concatenated paths if the client library does not enforce strict path semantics.

Firestore queries can also be vulnerable when order-by or where filters are constructed using unchecked request input. Consider a handler that builds a query like iter := client.Collection("products").Where("category", "==", category).Documents(ctx). If category is sourced directly from a query parameter without allowlisting, an attacker can inject logical combinations or special characters that change the query semantics or trigger errors that leak information about data structure.

In more advanced scenarios, injection can occur through Firestore map keys or field values if user input is used as a key and later interpreted by downstream code. Although Firestore does not support native code execution through its query language, injection here can facilitate data exfiltration by manipulating which documents are read or written, enabling horizontal or vertical privilege escalation within the application’s data model.

middleBrick detects these patterns as part of its Injection validation checks, analyzing OpenAPI specs and runtime behavior to identify places where untrusted input reaches Firestore operations. The scanner flags high-risk patterns such as dynamic collection names, unsanitized document IDs, and query constraints built from raw request parameters, providing prioritized findings with severity ratings and remediation guidance.

Firestore-Specific Remediation in Chi

Remediation focuses on strict input validation, allowlisting, and avoiding direct concatenation of user input into Firestore paths or queries. Always treat HTTP request data as untrusted and transform it before using it in Firestore operations.

1. Validate and sanitize document IDs:

import (
    "context"
    "fmt"
    "regexp"
    "strings"

    firestore "cloud.google.com/go/firestore"
    chi "github.com/go-chi/chi/v5"
)

func isValidDocID(id string) bool {
    // Allow alphanumeric, underscore, hyphen, and dot, length 1–1500
    matched, _ := regexp.MatchString(`^[a-zA-Z0-9_.-]{1,1500}$`, id)
    return matched
}

func getUserProfile(w http.ResponseWriter, r *http.Request) {
    userID := chi.URLParam(r, "userID")
    if !isValidDocID(userID) {
        http.Error(w, "invalid user identifier", http.StatusBadRequest)
        return
    }
    ctx := r.Context()
    client, err := firestore.NewClient(ctx, <your-project-id>)
    if err != nil {
        http.Error(w, "internal error", http.StatusInternalServerError)
        return
    }
    defer client.Close()

    docRef := client.Collection("users").Doc(userID)
    doc, err := docRef.Get(ctx)
    if err != nil {
        http.Error(w, "not found", http.StatusNotFound)
        return
    }
    // process doc.Data()
}

This pattern ensures document identifiers conform to a safe character set and length, preventing path traversal and injection via special characters.

2. Use allowlists for query parameters used in where clauses:

func listProducts(w http.ResponseWriter, r *http.Request) {
    category := chi.URLParam(r, "category")
    allowed := map[string]bool{
        "electronics": true,
        "books":        true,
        "clothing":     true,
    }
    if !allowed[category] {
        http.Error(w, "invalid category", http.StatusBadRequest)
        return
    }
    ctx := r.Context()
    client, err := firestore.NewClient(ctx, <your-project-id>)
    if err != nil {
        http.Error(w, "internal error", http.StatusInternalServerError)
        return
    }
    defer client.Close()

    iter := client.Collection("products").Where("category", "==", category).Documents(ctx)
    defer iter.Stop()
    for {
        doc, err := iter.Next()
        if err != nil {
            break
        }
        // process doc.Data()
    }
}

Allowlisting prevents injection by restricting values to a known set, eliminating unexpected query behavior.

3. Avoid using user input as Firestore map keys without normalization:

func storeUserMetadata(w http.ResponseWriter, r *http.Request) {
    userID := chi.URLParam(r, "userID")
    if !isValidDocID(userID) {
        http.Error(w, "invalid user identifier", http.StatusBadRequest)
        return
    }
    var input map[string]string
    if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
        http.Error(w, "invalid payload", http.StatusBadRequest)
        return
    }
    ctx := r.Context()
    client, err := firestore.NewClient(ctx, <your-project-id>)
    if err != nil {
        http.Error(w, "internal error", http.StatusInternalServerError)
        return
    }
    defer client.Close()

    // Normalize keys: restrict to alphanumeric and trim length
    normalized := make(map[string]string)
    for k, v := range input {
        cleanKey := regexp.MustCompile(`[^a-zA-Z0-9_]`).ReplaceAllString(k, "_")
        if cleanKey == "" || len(cleanKey) > 100 {
            continue
        }
        normalized[cleanKey] = v
    }

    docRef := client.Collection("user_metadata").Doc(userID)
    _, err = docRef.Set(ctx, normalized)
    if err != nil {
        http.Error(w, "failed to store", http.StatusInternalServerError)
        return
    }
}

Normalization reduces the risk of injection through map keys and ensures compatibility with downstream consumers.

Using middleBrick’s CLI, you can regularly scan your Chi endpoints to verify that these mitigations are effective: middlebrick scan <your-api-url>. For teams seeking continuous coverage, the Pro plan supports the GitHub Action to enforce security thresholds in CI/CD pipelines and provides compliance mapping to frameworks such as OWASP API Top 10 and SOC2.

Frequently Asked Questions

Can injection flaws in Firestore lead to data exposure even if authentication is enforced?
Yes. Injection flaws can allow an attacker to read or write documents they should not access by manipulating query filters or document paths. Proper input validation and allowlisting are required regardless of authentication.
Does middleBrick fix injection vulnerabilities automatically?
No. middleBrick detects and reports injection findings with remediation guidance. It does not modify code or block requests; developers must apply the suggested fixes.