HIGH email injectionginfirestore

Email Injection in Gin with Firestore

Email Injection in Gin with Firestore — how this specific combination creates or exposes the vulnerability

Email injection in a Gin application that uses Firestore typically arises when user-controlled input is placed into email headers or message bodies without validation or encoding, and the Firestore data store reflects or forwards that data to an email-sending step. For example, if a user profile document in Firestore contains a user-supplied displayName that is later concatenated into the Subject or To header of an email, newline characters (\n or \r) can break header structure and allow injection of additional headers or commands.

Gin does not provide built-in email-sending logic; the risk comes from how your route handlers build and pass data to the email service. A vulnerable pattern is reading a Firestore field directly and using it as a header value:

// Gin route example with potential injection via Firestore data
type UserProfile struct {
	Email string `json:"email" firestore:"email"`
	Name  string `json:"name" firestore:"name"`
}

func getUserProfile(client *firestore.Client) gin.HandlerFunc {
	return func(c *gin.Context) {
		uid := c.Param("uid")
		ctx := c.Request.Context()
		doc, err := client.Collection("profiles").Doc(uid).Get(ctx)
		if err != nil {
			c.JSON(500, gin.H{"error": "failed to fetch profile"})
			return
		}
		var profile UserProfile
		if err := doc.DataTo(&profile); err != nil {
			c.JSON(500, gin.H{"error": "failed to parse profile"})
			return
		}
		// Unsafe: profile.Name may contain \r\n used to inject extra headers
		c.JSON(200, gin.H{"email": profile.Email, "name": profile.Name})
	}
}

If profile.Name contains sequences like \r\nSubject: Urgent Reset, and your downstream email code uses this value unsanitized in header construction, an attacker can inject additional email headers. Firestore rules do not prevent this because the data is considered trusted from the application’s perspective; the injection occurs at the composition layer, not at Firestore itself.

The 12 parallel security checks in middleBrick would flag this as an Input Validation and BFLA/Privilege Escalation concern when user data influences email routing or headers. The scanner does not fix the code but provides prioritized findings with remediation guidance, such as validating and sanitizing header inputs and avoiding direct concatenation of user data into email headers.

In a full scan, middleBrick’s LLM/AI Security checks would not apply here because this issue is not related to prompt injection or model behavior; it is a classic injection vector mediated by improper handling of user-controlled data in email composition.

Firestore-Specific Remediation in Gin — concrete code fixes

Remediation focuses on strict validation, separation of data from control information, and safe formatting before using Firestore fields in email headers. Do not rely on Firestore security rules alone to prevent header injection; enforce rules in application code.

1) Validate and sanitize all user-derived data before using it in email headers. For headers like To and Subject, allow only a restricted character set and reject or encode newlines and control characters.

import "strings"
import "unicode"

func sanitizeHeader(value string) string {
	// Remove or replace carriage return and line feed characters
	value = strings.ReplaceAll(value, "\r", "")
	value = strings.ReplaceAll(value, "\n", "")
	// Optionally, trim spaces and limit length
	return strings.TrimSpace(value)
}

2) Use a dedicated email library that builds headers safely, and pass only verified data to it. For example, with net/smtp or a third-party library, ensure recipients and display names are sanitized:

import "github.com/jordan-wright/email"

func sendWelcomeEmail(to, name string) error {
	safeTo := sanitizeHeader(to)
	safeName := sanitizeHeader(name)
	e := email.NewEmail()
	e.From = "no-reply@example.com"
	e.To = []string{safeTo}
	e.Subject = "Welcome, " + safeName
	e.Text = []byte("Welcome to our service.")
	return e.Send("smtp.example.com:587")
}

3) When composing emails that include Firestore data, treat all Firestore document fields as untrusted input. Even fields like email should be validated with format checks and not directly used in headers without sanitization:

func composeMessageFromProfile(profile UserProfile) (string, string, error) {
	email := sanitizeHeader(profile.Email)
	if email == "" {
		return "", "", fmt.Errorf("invalid email")
	}
	// Validate email format with a simple check or a library
	name := sanitizeHeader(profile.Name)
	body := fmt.Sprintf("Hello %s, welcome back.", name)
	return email, body, nil
}

4) In Gin handlers, ensure that Firestore data is marshaled for safe response usage and that email composition occurs in a controlled context, not by concatenating raw strings for headers:

func getUserAndSendEmail(client *firestore.Client, mailer Mailer) gin.HandlerFunc {
	return func(c *gin.Context) {
		uid := c.Param("uid")
		ctx := c.Request.Context()
		doc, err := client.Collection("profiles").Doc(uid).Get(ctx)
		if err != nil {
			c.JSON(500, gin.H{"error": "failed to fetch profile"})
			return
		}
		var profile UserProfile
		if err := doc.DataTo(&profile); err != nil {
			c.JSON(500, gin.H{"error": "failed to parse profile"})
			return
		}
		email, body, err := composeMessageFromProfile(profile)
		if err != nil {
			c.JSON(400, gin.H{"error": "invalid profile data"})
			return
		}
		if err := mailer.Send(email, body); err != nil {
			c.JSON(500, gin.H{"error": "failed to send email"})
			return
		}
		c.JSON(200, gin.H{"status": "sent"})
	}
}

By applying these Firestore-aware sanitization steps in Gin, you reduce the risk of email header injection while keeping Firestore data flows explicit and auditable.

Frequently Asked Questions

Can Firestore security rules alone prevent email injection when data is used in email headers?
No. Firestore rules govern document read/write access but do not validate content for email header safety. Injection occurs at the composition layer; you must sanitize and validate data in your Gin code before using it in headers.
Does middleBrick fix the email injection findings it reports?
No. middleBrick detects and reports issues with remediation guidance; it does not fix, patch, block, or remediate. You must apply the recommended input validation and header sanitization in your Gin application.