Header Injection in Chi with Firestore
Header Injection in Chi with Firestore — how this specific combination creates or exposes the vulnerability
Header Injection in Chi using Firestore arises when user-controlled data is reflected into HTTP response headers without validation or encoding, and Firestore documents are used as the source of that data. Chi is a lightweight HTTP router for Go, and Firestore is a NoSQL database service. When a Chi handler retrieves a Firestore document and places a field value into a response header (e.g., X-Request-ID, X-Entity-Name), an attacker can manipulate the stored data or influence which document is read to inject newline characters that split headers or inject additional headers.
Consider a scenario where a Firestore document stores a display name used in a custom header. If the document is compromised or allows user-controlled input, and the handler does not sanitize newlines (\n or \r), an attacker can inject headers such as Content-Type or Set-Cookie. This violates the integrity of the HTTP message and can enable cross-site scripting (XSS) via response splitting, session fixation, or header manipulation attacks. The risk is compounded when Firestore queries use concatenated strings to build document paths or filters based on user input, potentially enabling path traversal or NoSQL injection that changes which document is read.
In practice, this maps to OWASP API Top 10 controls related to Improper Neutralization of Special Elements and Security Misconfiguration. Firestore rules may permit broad read access, and if a Chi endpoint exposes Firestore document fields in headers without context-aware validation, the unauthenticated attack surface increases. For example, an attacker who can control a Firestore field value might cause newline injection like \nX-Injected: true, which a vulnerable Chi handler places directly into the header block. Because the scan category Input Validation and Data Exposure tests for such injection risks, middleBrick would flag the endpoint with severity High and provide remediation guidance to enforce allowlists and encode header values.
Firestore-Specific Remediation in Chi — concrete code fixes
Remediation focuses on strict input validation, output encoding for headers, and defensive Firestore usage within Chi handlers. Never trust Firestore document fields that originate from user input or external sources. Use allowlists for known-safe values, avoid reflecting raw document fields into headers, and encode newlines and special characters appropriately.
Example of a vulnerable Chi handler that reflects a Firestore field into a header:
// Vulnerable example: do not use
func vulnerableHandler(w http.ResponseWriter, r *http.Request) {
docID := chi.URLParam(r, "docID")
ctx := context.Background()
client, _ := firestore.NewClient(ctx, "project-id")
defer client.Close()
doc, err := client.Collection("items").Doc(docID).Get(ctx)
if err != nil {
http.Error(w, "not found", http.StatusNotFound)
return
}
displayName, exists := doc.Data()["displayName"]
if !exists {
http.Error(w, "missing field", http.StatusBadRequest)
return
}
// Dangerous: injecting user-controlled data into header without validation/encoding
w.Header().Set("X-Display-Name", displayName.(string))
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
}
Secure remediation with validation and encoding:
// Secure example
func safeHandler(w http.ResponseWriter, r *http.Request) {
docID := chi.URLParam(r, "docID")
// Validate docID with an allowlist to prevent path traversal or NoSQL injection
if !isValidDocID(docID) {
http.Error(w, "bad request", http.StatusBadRequest)
return
}
ctx := context.Background()
client, _ := firestore.NewClient(ctx, "project-id")
defer client.Close()
doc, err := client.Collection("items").Doc(docID).Get(ctx)
if err != nil {
http.Error(w, "not found", http.StatusNotFound)
return
}
displayName, exists := doc.Data()["displayName"]
if !exists {
http.Error(w, "missing field", http.StatusBadRequest)
return
}
raw := displayName.(string)
// Validate and encode: allow only safe characters and replace newlines
safe := validateAndEncodeHeaderValue(raw)
w.Header().Set("X-Display-Name", safe)
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
}
func isValidDocID(id string) bool {
// Allow alphanumeric, hyphen, and underscore; reject path traversal or special chars
matched, _ := regexp.MatchString(`^[a-zA-Z0-9\-_]+$`, id)
return matched
}
func validateAndEncodeHeaderValue(value string) string {
// Remove or replace carriage return and newline to prevent header splitting
value = strings.ReplaceAll(value, "\r", "")
value = strings.ReplaceAll(value, "\n", "")
// Optionally enforce a length limit and allowlist characters
if len(value) > 200 {
value = value[:200]
}
return value
}
Additionally, secure Firestore usage includes tightening Firestore security rules to limit read access to only necessary fields and documents, and avoiding dynamic document paths constructed directly from user input. If your Chi application uses the Pro plan, you can enable continuous monitoring to detect when endpoints reflect Firestore fields in headers, and the GitHub Action can fail builds if a header-injection pattern is found in your API definitions.