#34753: Document how to safely construct email addresses
-------------------------------------+-------------------------------------
     Reporter:  Sylvain Fankhauser   |                    Owner:  Mike
         Type:                       |  Edmunds
  Cleanup/optimization               |                   Status:  assigned
    Component:  Documentation        |                  Version:
     Severity:  Normal               |               Resolution:
     Keywords:  email                |             Triage Stage:  Accepted
    Has patch:  1                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  1
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Changes (by Mike Edmunds):

 * owner:  (none) => Mike Edmunds
 * status:  new => assigned

Comment:

 Copying in some of my notes (from a comment in the earlier PR):

 I think we need to substantially rework the whole text in the section, so
 it emphasizes the part that's the *developer's* responsibility (preventing
 email address syntax injection). I'm not sure how best to word it, but
 here's what I'd want to convey and roughly the order:

 * Email header injection is a security exploit in which an attacker
 manipulates email headers to change the intended sender, recipients, other
 headers, or even the entire message.
 * Header injection can be caused by newlines in header values (CRLF
 injection) or by certain characters like commas and parentheses in address
 headers (address syntax injection). [There doesn't seem to be a standard
 term for the second type. We could instead say "header content injection"
 or "delimiter injection".]
 * Django builds on Python's email library, which prevents CRLF injection.
 You'll get a `ValueError` if you try to send a message with newlines in
 header values.
 * But Django can't protect you from address syntax injection. **You are
 responsible for properly sanitizing email addresses** constructed from
 user-supplied or variable data.
 * The best way to construct email addresses is using a well-tested library
 function intended for the purpose, like Python's
 `email.headerregistry.Address` object or (if you don't need IDN support)
 the legacy `email.utils.formataddr()` function. (See example below.)
 * **Never** try to use string formatting like `f'"{name}" <{email}>'` to
 compose an email address header. This is unsafe, just like building SQL or
 HTML with string formatting.
 * If you're sending email that includes user-supplied content, you'll
 likely need to take steps to prevent spoofing, spear-phishing, spam
 cannons, and other malicious uses of email. (Details are beyond the scope
 of Django docs.)
 * Here's an example contact form that demonstrates some of these concepts…

 Also, I've been trying to find a replacement link for
 http://www.nyphp.org/phundamentals/8_Preventing-Email-Header-
 Injection.html, which is heavily PHP centric and a bit outdated. All the
 general descriptions I could find cover only CRLF injection, not address
 syntax injection. (And they all use similar PHP code examples.) But maybe
 one of these? Most are commercial sites; don't know if we have a policy
 about that:
 * https://beaglesecurity.com/blog/vulnerability/email-header-
 injection.html
 * https://www.invicti.com/learn/email-injection
 * https://www.acunetix.com/blog/articles/email-header-injection/ (same
 content, related company, different formatting)
 * https://en.wikipedia.org/wiki/Email_injection (stub article)
-- 
Ticket URL: <https://code.djangoproject.com/ticket/34753#comment:11>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/django-updates/0107019e93d4849c-f46859e7-94c4-4743-a398-dcf3e1cf7fd8-000000%40eu-central-1.amazonses.com.

Reply via email to