Opened 7 years ago

Closed 7 years ago

Last modified 4 years ago

#7472 closed (wontfix)

Potentially sensitive information leaked if an error occurs when a page is served over HTTPS

Reported by: frasern Owned by: nobody
Component: HTTP handling Version: master
Severity: Keywords:
Cc: me@… Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:


If an error occurs while processing a request, Django sends an email to those defined in settings.ADMIN. This email contains a repr of the request object, which includes GET and POST data amongst other things. If the request came in over HTTPS then potentially very sensitive information could be leaked as plain text in the email.

HTTPS is designed to secure the transmission of the data between the browser and the server. The issue here is that the contents of Django's error email is not encrypted, so that as it travels from the web server to the admins' email servers it is in plain text form which any "man in the middle" could read.

The attached patch simply omits the request details if HTTPS was used.

I've discussed this with Jacob on the security mailing list and he's asked me to raise a ticket with this patch and assign it as 1.0 item.

Attachments (2)

7472.patch (1.2 KB) - added by frasern 7 years ago.
7472-2.patch (3.5 KB) - added by frasern 7 years ago.

Download all attachments as: .zip

Change History (12)

Changed 7 years ago by frasern

comment:1 Changed 7 years ago by Simon Greenhill

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Triage Stage changed from Unreviewed to Accepted

comment:2 Changed 7 years ago by durdinator

  • Cc me@… added

comment:3 Changed 7 years ago by telenieko

  • Patch needs improvement set

That should also patch the relevant documentation alerting users that mails from HTTPS connections won't have request info.

Changed 7 years ago by frasern

comment:4 Changed 7 years ago by frasern

  • Patch needs improvement unset

I've attached an updated patch which provides some documentation of the new behaviour.

I also noticed that the 404 notification emails have the same issue of potentially leaking sensitive data, so this patch also provides a fix in that part of the code too.

comment:5 Changed 7 years ago by ubernostrum

Erm. Isn't this what secure email is for?

comment:6 Changed 7 years ago by mtredinnick

I'm -1 on this. It's a faux solution in a way, since it doesn't cover sensible setups like Apache accepting an HTTPS connection forwarding to another web server on the same machine that runs the Django stuff (using HTTP, since it's intra-machine).

Secondly, it's solving a sysadmin problem at the wrong level (and everybody has to pay the price of not seeing that information). The right solution is to use TLS email connections in this case. Django supports that already. If it's considered useful to send the request information, it should always be sent. Otherwise, never sent. As noted, HTTPS protects the browser to server path. It's not an indication or predictor of internal sysadmin or network requirements.

comment:7 Changed 7 years ago by ubernostrum

Malcolm said it better. And for the record, I already do this, it's ludicrously easy and, in fact, I can't do anything else: my hosting service doesn't permit me to use non-TLS connections to send mail, and doesn't permit me to use non-TLS connections to retrieve my mail. This is very much a configuration issue with an easy solution for anyone paranoid enough to worry about it.

comment:8 Changed 7 years ago by frasern

My understanding is that the EMAIL_USE_TLS setting is only used to provide a secure connection between Django and the EMAIL_HOST. The EMAIL_HOST will probably then relay the message onwards to the destination mailserver of each of the ADMINS over connections which are not required to be secure.

Imagine the following scenario:

  • The Django web server is at
  • The web server uses to send outbound messages securely (i.e. EMAIL_HOST = '' and EMAIL_USE_TLS = True).
  • ADMINS is set to (('John Doe', ''),).
  • The MX record of is

So, when an error occurs, the error notification email would be relayed as follows:

+-----------------+    TLS    +------------------------+   plain   +------------------+
| | --------> | | --------> | |
+-----------------+           +------------------------+   text    +------------------+

Even if TLS is used between and, there is absolutely no guarantee that the communication between and will be secure; RFC3207 states:

A publicly-referenced SMTP server MUST NOT require use of the STARTTLS extension in order to deliver mail locally. This rule prevents the STARTTLS extension from damaging the interoperability of the Internet's SMTP infrastructure. A publicly-referenced SMTP server is an SMTP server which runs on port 25 of an Internet host listed in the MX record (or A record if an MX record is not present) for the domain name on the right hand side of an Internet mail address.

Also, TLS does not provided end-to-end encryption like HTTPS does, but rather only provides security between two directly communicating servers. In the example above, could be be run by an untrusted party such as your hosting ISP, so cannot really be considered secure. Again, from RFC3207:

It should be noted that SMTP is not an end-to-end mechanism. Thus, if an SMTP client/server pair decide to add TLS privacy, they are not securing the transport from the originating mail user agent to the recipient. Further, because delivery of a single piece of mail may go between more than two SMTP servers, adding TLS privacy to one pair of servers does not mean that the entire SMTP chain has been made private.

With regard to having a public-facing HTTPS server delegating to a secondary internal web server over HTTP, I would have thought the secondary server would want to know the request originated over HTTPS otherwise you may have trouble with other things such as the common request.is_secure() and 'https' or 'http' construct for building absolute URLs.

I appreciate that completely omitting the details of the request may not ideal; however it would appear that currently the only way to prevent request information being from sent when an error occurs would be to set ADMINS to (). This has the significant downside that you wouldn't receive notification of the error at all.

It may be preferable to have some facility to allow the standard error email construction to be overridden. This would allow you to decide yourself what should go in the error notification email and even allow you to encrypt it using something like S/MIME.

I guess you can already achieve something like this by connecting to the got_request_exception signal. However, I really think in its default configuration Django should be sensible enough to know that if HTTPS was used then the request information should not be forwarded on over an insecure email channel.

comment:9 Changed 7 years ago by jacob

  • Resolution set to wontfix
  • Status changed from new to closed

While I appreciate the problem, this isn't something that we need to do for Django. Besides what Malcolm and James said, there's another, even simpler fix: if you're this security-concious, just don't send error emails (use some other notification logging system).

comment:10 Changed 4 years ago by jacob

  • milestone 1.0 beta deleted

Milestone 1.0 beta deleted

Note: See TracTickets for help on using tickets.
Back to Top