Formula Injection in Gin with Firestore
Formula Injection in Gin with Firestore — how this specific combination creates or exposes the vulnerability
Formula Injection occurs when an attacker-supplied value is interpreted as a formula or expression by a downstream system such as a spreadsheet processor or database engine that evaluates expressions. When a Go web service built with the Gin framework writes user-controlled data into Firestore documents that are later exported to tools capable of evaluating formulas (for example, Google Sheets or downstream data pipelines), the data can be treated as executable expressions rather than plain text.
In Gin, if request parameters or JSON payload fields are bound directly into Firestore document fields without normalization or escaping, an attacker can supply values such as =1+1 or =HYPERLINK("https://evil.example", "click"). Firestore itself does not evaluate formulas, but the vulnerability arises when exported data is opened in a spreadsheet or consumed by a service that does. For example, a reporting endpoint that exports Firestore query results into a CSV and triggers a Sheets import can lead to arbitrary formula execution in the context of the viewer’s account, enabling phishing, data exfiltration, or social engineering via crafted expressions.
The risk is compounded when the Firestore data is used in downstream automation. Consider a Gin handler that writes a user-controlled note field into a Firestore document used later by a data processing job that generates spreadsheets. An input such as =cmd|' /K calc'!A0 (in older spreadsheet syntax) or a Google Sheets expression like =IMAGE("https://example.com/malicious.png") will be rendered as a formula when the sheet opens, potentially executing network requests or launching system commands depending on the client and configuration.
Because Firestore supports structured data and nested maps, attackers may also attempt to inject formula-like payloads into numeric or string fields that later feed into computed columns or aggregations in client applications. If a client-side application reads Firestore data and writes it into a worksheet without escaping, the injected formula executes in the viewer’s session, leveraging their permissions. This cross-context pollution—shifting from Firestore’s document model to a formula-evaluating environment—creates the practical exploit path.
To detect this pattern, scanning with middleBrick can surface unvalidated user input flowing into Firestore fields that are later exported or used in contexts where expression evaluation is possible. middleBrick’s checks include Data Exposure and Unsafe Consumption, which help identify places where untrusted data is stored without sufficient sanitization, and the LLM/AI Security module can probe for indirect prompt-injection-style techniques that manipulate downstream behavior.
Firestore-Specific Remediation in Gin — concrete code fixes
Remediation focuses on ensuring that data written to Firestore is never interpreted as executable expressions when later exported or rendered. Treat all user input as opaque data, apply context-aware escaping when exporting, and avoid concatenating raw request values into Firestore document fields.
1. Validate and sanitize inputs before writing to Firestore
Use allow-lists and strict type checks for known fields. For string fields, reject or neutralize characters commonly used in formulas such as =, +, -, @, and control characters. For identifiers, prefer UUIDs or server-generated keys rather than user-provided values.
package main
import (
"context"
"fmt"
"net/http"
"regexp"
"github.com/gin-gonic/gin"
"cloud.google.com/go/firestore"
googleapi "google.golang.org/api/option"
)
// sanitizeInput rejects formula-like prefixes and dangerous characters.
func sanitizeInput(value string) (string, error) {
if matched, _ := regexp.MatchString(`^\s*[=+ -@]`, value); matched {
return "", fmt.Errorf("invalid input: potential formula injection")
}
// Optionally, escape leading equals signs if you must preserve content.
if len(value) > 0 && value[0] == '=' {
value = "'" + value // Prefix with apostrophe to force text interpretation in spreadsheets
}
return value, nil
}
func createDocument(c *gin.Context, client *firestore.Client) {
var payload struct {
Title string `json:"title"`
Note string `json:"note"`
}
if err := c.ShouldBindJSON(&payload); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
title, err := sanitizeInput(payload.Title)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
note, err := sanitizeInput(payload.Note)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
_, err = client.Collection("entries").Add(c, map[string]interface{}{
"title": title,
"note": note,
"ts": firestore.ServerTimestamp,
})
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusCreated, gin.H{"status": "ok"})
}
2. Escape or transform data on export
If you generate spreadsheets or CSVs from Firestore data, prefix cells that could be misinterpreted as formulas with an apostrophe (Google Sheets, Excel) or wrap values in quotes. Do this in the export layer, not by changing the stored document, to preserve data integrity.
// exportToCSV demonstrates safe CSV generation from Firestore docs.
import (
"encoding/csv"
"os"
)
func exportToCSV(entries []Entry) {
f, _ := os.Create("export.csv")
defer f.Close()
w := csv.NewWriter(f)
defer w.Flush()
for _, e := range entries {
// Prefix fields that start with =, +, -, @ to prevent formula interpretation.
title := e.Title
note := e.Note
if len(title) > 0 && (title[0] == '=' || title[0] == '+' || title[0] == '-' || title[0] == '@') {
title = "'" + title
}
if len(note) > 0 && (note[0] == '=' || note[0] == '+' || note[0] == '-' || note[0] == '@') {
note = "'" + note
}
_ = w.Write([]string{title, note})
}
}
3. Use middleBrick to validate your configuration and exposed surface
Run middleBrick scans against your Gin endpoints to confirm that user-controlled fields are not reflected into Firestore without validation. The dashboard and CLI can help you track changes over time and integrate checks into CI/CD so that new endpoints are assessed before deployment.
middleBrick’s findings map to OWASP API Top 10 and compliance frameworks, and the Pro plan adds continuous monitoring so future changes are flagged before they reach production.