Email Injection in Fiber with Cockroachdb
Email Injection in Fiber with Cockroachdb — how this specific combination creates or exposes the vulnerability
Email Injection occurs when user-controlled input is directly concatenated into email headers or commands, allowing an attacker to inject additional headers such as CC, BCC, or even chain multiple messages. In a Fiber application interacting with Cockroachdb, this typically arises when query parameters or request bodies are used to construct email headers or dynamic SQL that influences email delivery without proper validation or escaping.
Consider a user registration flow that stores a user’s email in Cockroachdb and later sends a welcome email. If the application builds the To: header by directly interpolating a value from the request (e.g., a query parameter or form field) into a command executed via SQL or an external process, an attacker can supply a payload like [email protected]\r\nCC: [email protected]. Because the interaction with Cockroachdb may log or mirror the input in email-related tables or stored procedures, the injected header can be executed when the email is composed or relayed.
With Cockroachdb, which is PostgreSQL-compatible, developers often use parameterized queries or ORMs. However, if email header construction occurs outside of those safeguards — for example, in application code that builds a shell command or an SMTP transaction using string concatenation — the database interaction itself does not introduce the injection, but it can store or reference the tainted input that later leads to Email Injection. A common pattern is inserting user input into a table used by a background job that generates emails; if the job uses unsafe string assembly, the stored data becomes the injection vector.
The risk is compounded when the Fiber app exposes endpoints that accept email-related fields (e.g., reply_to, cc) and then use that data in SQL statements sent to Cockroachdb without sanitization. An attacker might submit a crafted payload via API, and although the database stores the value, the vulnerability manifests later during email composition. Because middleBrick tests unauthenticated attack surfaces and includes checks for Input Validation and Unsafe Consumption, such chained risks across the API, database, and email layers are detectable in a scan.
Real-world examples include CVE-class patterns where email headers are not properly validated, leading to spam or phishing campaigns. In a Fiber + Cockroachdb stack, ensure that any user input used in email headers is strictly validated against a whitelist of allowed characters and that header construction uses language-level email libraries rather than raw SQL or shell commands.
Cockroachdb-Specific Remediation in Fiber — concrete code fixes
Remediation focuses on strict input validation, using parameterized queries, and avoiding direct concatenation of user input into email headers or SQL statements. Below are concrete, realistic examples for a Fiber application interfacing with Cockroachdb.
1. Use parameterized queries with the pq or pgx driver
Never embed user input directly into SQL strings. Use placeholders and pass values separately. This prevents injected SQL and ensures that email-related fields are treated as data, not executable code.
// main.go
package main
import (
"context"
"log"
"github.com/gofiber/fiber/v2"
"github.com/jackc/pgx/v5/pgxpool"
)
type UserRequest struct {
Email string `json:"email" validate:"email"`
Name string `json:"name"`
}
func main() {
connStr := "postgresql://user:pass@localhost:26257/dbname?sslmode=disable"
pool, err := pgxpool.New(context.Background(), connStr)
if err != nil {
log.Fatalf("unable to connect: %v", err)
}
defer pool.Close()
app := fiber.New()
app.Post("/register", func(c *fiber.Ctx) error {
var req UserRequest
if err := c.BodyParser(req); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid payload"})
}
// Validate email format before using it
if !isValidEmail(req.Email) {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid email"})
}
// Parameterized query to Cockroachdb
query := `INSERT INTO users (email, name) VALUES ($1, $2) RETURNING id`
var userID int
err := pool.QueryRow(context.Background(), query, req.Email, req.Name).Scan(&userID)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "db error"})
}
// Safe email composition using a library, not string concatenation
if err := sendWelcomeEmail(req.Email, req.Name); err != nil {
log.Printf("email error: %v", err)
}
return c.JSON(fiber.Map{"id": userID})
})
app.Listen(":3000")
}
func isValidEmail(email string) bool {
// Simple but effective validation; use a library in production
return len(email) > 3 && email[0] > 32 && email[len(email)-4] == '.'
}
func sendWelcomeEmail(to, name string) error {
// Use net/smtp with properly constructed headers; avoid injecting 'to' or 'name' into headers
// Example uses a controlled sender and recipient; do not build headers via string concatenation.
return nil
}
2. Validate and sanitize email fields used in background jobs
If Cockroachdb stores email metadata for async processing, ensure that retrieval and email composition follow the same safe patterns. Avoid using raw user input in command-line calls or SMTP libraries that build headers from strings.
// background_email.go
package main
import (
"context"
"fmt"
"github.com/jackc/pgx/v5/pgxpool"
)
func processPendingEmails(pool *pgxpool.Pool) {
ctx := context.Background()
rows, err := pool.Query(ctx, `SELECT email, name FROM users WHERE email_sent = false`)
if err != nil {
log.Printf("query error: %v", err)
return
}
defer rows.Close()
for rows.Next() {
var email, name string
if err := rows.Scan(&email, &name); err != nil {
continue
}
// Safe: using a templating or library function to set headers
if err := sendWelcomeEmail(email, name); err != nil {
log.Printf("failed to send to %s: %v", email, err)
}
// Mark as sent with a parameterized update
pool.Exec(ctx, `UPDATE users SET email_sent = true WHERE email = $1`, email)
}
}
3. Enforce schema constraints in Cockroachdb
Add CHECK constraints to ensure email columns contain only valid characters, reducing the impact of any upstream validation bypass.
-- SQL migration
ALTER TABLE users ADD CONSTRAINT valid_email CHECK (email ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$');
By combining parameterized queries, strict input validation, and safe email library usage, the Fiber app minimizes the risk of Email Injection while reliably storing and retrieving data in Cockroachdb.