Safeguard
Application Security•

ASVS 5.0 V1.3.11: Prevent SMTP and IMAP Injection

ASVS V1.3.11 requires sanitizing user input before it reaches mail systems. Learn to block header injection in contact forms and test your mailer.

Safeguard Security Team
2 min read

ASVS 5.0 V1.3.11 (Level 2) requires that user input is sanitized before it is passed to mail systems, to protect against SMTP and IMAP injection. In practice, this means rejecting carriage returns and line feeds in any value that becomes a header or protocol command.

Why it matters

A contact form that places a visitor's address in a From or Reply-To header can be abused: an address followed by \r\nBcc: victims@example.com adds recipients, and your server becomes a spam relay with your domain's reputation. The same line break trick can inject extra commands into raw SMTP or IMAP sessions.

How to implement it

Use a mail library with a structured message API, never raw header strings, and validate fields.

from email.message import EmailMessage
from email.utils import parseaddr

def build(to_addr: str, subject: str, body: str) -> EmailMessage:
    for v in (to_addr, subject):
        if "\r" in v or "\n" in v:
            raise ValueError("line break in header value")
    name, addr = parseaddr(to_addr)
    if not addr or "@" not in addr:
        raise ValueError("bad address")
    msg = EmailMessage()
    msg["To"] = addr
    msg["Subject"] = subject
    msg.set_content(body)
    return msg

Modern libraries refuse line breaks in headers, but check yours. Do not let users set recipients freely. Send contact form mail to a fixed address and put the visitor's email only in the body or Reply-To after validation. For IMAP, quote search terms using the library's escaping and never build commands by concatenation.

How to test it

Submit a@example.com%0d%0aBcc:x@example.com and the same with a literal line break in the address, name and subject fields. Check the sent message headers in a test inbox: there must be no extra Bcc or header.

Common mistakes

  • Validating the email format with a pattern that allows line breaks.
  • Letting the subject or name carry a line break.
  • Using the mail() function of a language with raw header strings.

Quick check

Which characters enable header injection?

Carriage return and line feed. Reject both in any value that ends up in a header or command.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.