Email Address Disclosures, Preliminary Report
community.letsencrypt.org
community.letsencrypt.org
Our sincerest apologies for this mistake. We will be doing a thorough postmortem to determine exactly how this happened and how we can prevent something like this from happening again.
There is a preliminary report on the issue here:
https://community.letsencrypt.org/t/email-address-disclosure...
(There would probably not be a fine; the company would be investigated and warned by the various regulators).
Once your email is out there, there's no going back.
Email addresses are personally identifiable information, and revealing a relationship between a business and a person is potentially very dangerous.
For example: http://www.bbc.co.uk/news/technology-36247186
If you look at the past 5 years, there is almost not a single major website that hasn't been hacked and hasn't leaked personal data. Not only do I see no sign of improvement, but it is rather accelerating. Leaking information on 30m+ people is now becoming common and barely makes the news outside of a few specialized websites like HN.
If you have a better alternative than feeding garbage data to websites who want to collect data they won't need (why would an online retailer give a shit that they are shipping a product to someone called Mr X rather than Mr Y?), I want to hear it.
> Each supervisory authority shall have all of the following corrective powers:
> [...]
> (b) to issue reprimands to a controller or a processor where processing operations have infringed provisions of this Regulation;
(IANAL)
See this recent example, where a sexual health centre accidentally leaked a list of 800 people who had attended HIV clinics.
They ended up with a £180,000 fine: http://www.bbc.co.uk/news/technology-36247186
If I'd been affected by this Let's Encrypt email thing I frankly wouldn't care, other than to question why it happened. (Just speaking for myself, I'm sure some people would care.) But if I was data in a leak revealing a personal serious medical issue, I absolutely would care.
For those interested, I can highly recommend the documentary Democracy: Im Rausch der Daten (2015) [0]. For 9 month the documentary follows MEP rapporteur Jan Philipp Albrecht and his policy advisor Ralf Bendrath [1] (hacked a C64 in his youth, frequent attendee at C3) and gave a rare inside in the negotiation & process in Brussels. They even recorded the final negotiations in the backrooms and for those knowledgeable on the topic it is very interesting to see how some of the deals where made. After the screening at IDFA the director said he wasn't onset to make a documentary on the EU data protection reform and that Jan Phillip's rapporteur topic was chosen as an example EU process. Regretfully this documentary isn't exemplary for the EU process because most of the time the lobbyists of the large corporations have a far larger influence. The documentary clearly shows that the final text has been the result of the persistence & integrity of the the 3 main characters Albrecht, Bendrath and Redding. And as we're experience now, this has great influence on data protection for more than only Europe.
[0] http://www.democracy-film.de http://www.imdb.com/title/tt5053042/
The whole mess was caused by the Python `email` package, and specifically the behavior of the `MIMEMultipart` object [2]. When you reuse the same `MIMEMultipart` object for multiple emails, each destination address is appended. The same problem takes place when you use Python 3 [3].
[1]: https://twitter.com/0xjosh/status/741487697059946497
[2]: https://docs.python.org/3/library/email.mime.html#email.mime...
getEmailBody(users[:i])
instead of getEmailBody(users[i])
I typically prefer a high level of polymorphism in my code/APIs (sensibly handling single inputs vs. arrays) but this is a great counter-example even if not the actual root cause. Every feature is also a liability. Double edged sword. Etc. for user in users:
getEmailBody(user)
instead of for i in range(len(users)):
getEmailBody(users[i])
(for the languages that let you do so). sendUserEmail :: FromEmail -> ToEmail -> [EmailHeader] -> EmailBody -> IO ()
However that also requires the discipline of wrapping a lower level function that is probably: sendEmails :: FromEmail -> [ToEmail] -> [EmailHeader] -> EmailBody
However even a functional language would shy away from using indexing which could be argued to be the source of this problem.So your "type system can really help" is really just an irrelevancy you've come up with to try hide your attempt to shove your preferred programming paradigm onto other people.
You should probably stop doing that.
passing it a list makes the recipients arg a list with a list of recipients. To actually send to multiple recipients I explicitly have to use the apply procedure that passes all list elements as arguments.
as you said, not a staticly typed language. types would have made an eventual error easier to debug though.
Not exactly, but it is a weaker advantage than I thought when writing it. The advantage is that languages like Haskell encourage specializing functions in that manner which avoid that specific bug.
However so does test driven development which is just as possible in dynamic languages.
The advantage the statically typed language has over even the dynamically typed language plus tdd is that the program won't compile whereas dynamic language plus tdd relies on programmer discipline.
// JavaScript
if ( Array.isArray(address) ) {
throw new Error("Must only pass a single email address.");
}
// Java
void sendEmail(Object recipientOrRecipients) { ... }
There are times when polymorphism is low-risk, and there are times when it's better safe than sorry. Best to know your risk model (and your libraries) and act accordingly.Assignment is interpreted as add-to-the-list operator.
Python 2.7: https://hg.python.org/releasing/2.7.9/file/tip/Lib/email/mes...
Python 3.4: https://hg.python.org/releasing/3.4/file/tip/Lib/email/messa...
Ouch.
as far as I know, all emails starting with 0-9, A-Z and at least part of 'a' were exposed. I did not get one starting with 'g', so it's somewhere between 'a' and 'g' that it got stopped.
Edit: "7,618 out of approximately 383,000 emails" were sent out
Edit: Just want to add that I've made a similar mistake before (with a smaller user base). So I understand how easily these bugs occur. Given all their progress in the last few years, I still believe that the privacy and security of such a large portion of the Web could not be in better hands. Props to the LE team for a quick, responsible response.
http://docs.quantifiedcode.com/python-anti-patterns/correctn...
A comedy of errors....
"Dear Let's Encrypt Subscriber,
We're writing to let you know that we are updating the Let's Encrypt Subscriber Agreement, effective June 30, 2016. You can find the updated agreement (v1.1) as well as the current agreement (v1.0.1) in the "Let's Encrypt Subscriber Agreement" section of the following page:
https://letsencrypt.org/repository/
Thank you for helping to secure the Web by using Let's Encrypt"
What's the limit for numbers of addresses in a CC field? Because this is several thousand addresses.
The actual spec though, AFAIK, has no limit.
1. https://www.ietf.org/rfc/rfc2822.txt §2.2.3
In other words, delivering a message to copious CC: recipients is not an uninterruptable operation even after the MUA has finished its job. They might have had to/been able to stop the local MTA to interrupt the rogue emails.
In that event, it is interruptible.
Also, the MTA will batch its own outgoing sends to individual servers (giving them either just one rcpt to or all the recipients whose MX map to that server) and it could be interruptible there as well.
The point is that when sending to many many delivery addresses, things get batched at various stages and become more interruptible than if your CC was the master list of how a message were routed.
One would also think that most subscribers of this newsletter has a positive attitude towards the general concepts of privacy and security, so I'm also positive in thinking that a list of these disclosed addresses will never see the day of light (hoping I'm not too naive).
The correct behavior is to be able to request a marker when signed into any email account, and on my side set the tag that it gets tagged with in that inbox as a result. The link between marker and inbox should remain secret.
500 is a reasonable limit I think, in case spamming would be some reason for them not to do this. I don't have an opinion about whether people should be able to send from marker@gmail.com or if it should just end up in a real inbox but without the ability to send from that address.
If Gmail gets compromised, you'd need to be looking for a bunch of Fastmail accounts in To: addresses to link my primary email with those emails.
If you wanted to track me down from an email address, you'd need a warrant in Australia (for FastMail), and the US (to find the account using those FastMail credentials), so I'd need to have actually done something wrong (which I haven't), and you'd need to convince judges in two jurisdictions of that. As I said, the threat model is against casual snoopers, rather than a determined state actor with proof of wrong-doing, as I don't think I'm even slightly interesting and I don't think I've done anything that would make me interesting.
As it turns out, you could probably just read enough of my FastMail email as it came in (before it gets deleted by Gmail) to figure out who I am, so this is imperfect.
[0] https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-...
Did you sign up in the earlier or later stages?
They tend to take a warn then fine approach.
What if someone MITM's your site, injects some code so that when the user clicks on the checkout link/button they get sent to a malicious site?
> "Hey there! Looks like you're enjoying the discussion, but you're not signed up for an account.
> When you create an account, we remember exactly what you've read, so you always come right back where you left off. You also get notifications, here and via email, whenever new posts are made. And you can like posts to share the love."
> [Sign up] [Remind me tomorrow]
No thanks :)
The rest of me which is more jaded and bitter knows that it won't.