HIGH email injectionactixhmac signatures

Email Injection in Actix with Hmac Signatures

Email Injection in Actix with Hmac Signatures — how this specific combination creates or exposes the vulnerability

Email Injection in Actix occurs when user-controlled input is placed into email headers without strict validation or sanitization, and the endpoint is protected only by an Hmac Signature. In this scenario, an attacker can inject additional header lines (e.g., CC, BCC, or injected recipients) by supplying newline characters such as %0a or %0d%0a in parameters that are signed but not canonicalized before signing. The Hmac Signature verifies integrity of the signed payload, but if the payload is built by concatenating raw user input into email headers, the signature remains valid while the resulting message is altered in unexpected ways.

Consider an Actix web service that sends a confirmation email. The request body includes email, callback_url, and an Hmac signature in a header computed over a canonical string such as email|callback_url|timestamp. If the service places the email value directly into the To or Cc header and does not reject or encode newline characters, an attacker can provide an email like victim@example.com%0a%0dcc: attacker@evil.com. The Hmac signature will still verify because the canonical pre-hash string includes the raw input; however, the resulting email contains an additional recipient, enabling email injection.

This pattern is especially risky when the Hmac is computed over a subset of fields while other fields are appended to the email headers server-side. For example, if the signature covers the JSON body but the server then builds SMTP headers by interpolating the email field without normalization, the signed integrity guarantee does not protect the header construction phase. OWASP API Top 10 A03:2023 (Injection) and related email injection techniques map to this weakness, where control characters break the intended header structure.

In an unauthenticated scan, middleBrick would flag this as an input validation and data exposure concern: the endpoint reflects or sends messages to injected addresses, and sensitive information (e.g., internal relay details) might be exfiltrated via injected headers. The scanner tests whether newline characters in signed fields can alter the runtime behavior of email generation without invalidating the Hmac Signature.

Hmac Signatures-Specific Remediation in Actix — concrete code fixes

To remediate Email Injection in Actix while preserving Hmac Signature integrity, canonicalize and strictly validate all user-supplied data before it participates in both the signed payload and any email header construction. Use a two-stage approach: first, validate and normalize inputs; second, include only normalized values in the Hmac computation and header assembly.

In Actix web, define a handler that validates email addresses with a strict regex and rejects any input containing carriage return or line feed characters. Then, build the Hmac payload from the normalized values, and use a safe email library to construct headers so that user input never directly forms header lines.

use actix_web::{post, web, HttpResponse, Result};
use hmac::{Hmac, Mac};
use sha2::Sha256;
type HmacSha256 = Hmac;

fn normalize_email(raw: &str) -> Result {
    // Reject newlines and carriage returns to prevent header injection
    if raw.contains('\n') || raw.contains('\r') {
        return Err("invalid_email");
    }
    // Basic format check
    let email = raw.trim().to_lowercase();
    if email.contains('@') && email.contains('.') {
        Ok(email)
    } else {
        Err("invalid_email")
    }
}

fn build_hmac_signature(email: &str, callback_url: &str, timestamp: &str, key: &[u8]) -> String {
    let mut mac = HmacSha256::new_from_slice(key).expect("HMAC can take key of any size");
    // Canonical order and no extra delimiters that could be manipulated
    mac.update(email.as_bytes());
    mac.update(b"|");
    mac.update(callback_url.as_bytes());
    mac.update(b"|");
    mac.update(timestamp.as_bytes());
    let result = mac.finalize();
    hex::encode(result.into_bytes())
}

#[post("/confirm")]
async fn confirm(
    form: web::Form,
    secret: web::Data>,
) -> Result {
    let email = normalize_email(&form.email)?;
    let callback_url = normalize_url(&form.callback_url)?;
    let timestamp = chrono::Utc::now().timestamp().to_string();

    let signature = build_hmac_signature(&email, &callback_url, ×tamp, &secret);

    // Compare signature from header (example) — in practice use constant-time compare
    // Send email using a safe builder; user input is only in the address body, not raw header lines
    let message = format!("To: {}\nSubject: Confirmation\n\nPlease confirm: {}", email, form.email);
    // Assume send_mail is a function that uses a proper SMTP client library
    send_mail(&message).map_err(|_| actix_web::error::ErrorInternalServerError("send failed"))?;

    Ok(HttpResponse::Ok().body("Confirmation sent"))
}

fn normalize_url(raw: &str) -> Result {
    if raw.contains('\n') || raw.contains('\r') {
        return Err("invalid_url");
    }
    // Further normalization as needed
    Ok(raw.trim().to_string())
}

In this example, the email field is validated and normalized before inclusion in the Hmac computation, ensuring that the signed canonical string and the email header content are aligned. The Hmac Signature covers the normalized email, preventing an attacker from injecting newline characters that would be accepted by the signature check but cause the server to append additional recipients.

Additionally, use a dedicated email library to construct headers instead of string concatenation. This prevents accidental injection even if future code changes inadvertently pass raw user input to header-building logic. middleBrick’s scans can verify that endpoints with Hmac protections still reject newline-injected values by testing with payloads such as victim%40example.com%0aCc%3a%20attacker%40evil.com and observing whether the signature validation and header parsing remain consistent.

Frequently Asked Questions

How can I test my Actix endpoint for email injection with Hmac signatures using middleBrick?
Run a middleBrick scan on your endpoint. The scanner will submit newline-encoded values in signed fields and observe whether the Hmac signature remains valid while the runtime behavior changes (e.g., additional recipients). Use the CLI: middlebrick scan , or add the GitHub Action to CI/CD to automate this check on each deployment.
Is removing user input from email headers the only fix, or can I keep dynamic recipients safely?
You can allow dynamic recipients if you strictly validate and sanitize each address: reject control characters, normalize case, and ensure addresses are placed only in the message body or assigned via a safe email builder. The Hmac signature must cover the canonical representation of these normalized values, and header construction must be done via a library rather than string interpolation.