diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index 801ae728dd1364..c09f4f121ffb63 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -1585,6 +1585,8 @@ def get_domain(value): token, value = get_dot_atom(value) except errors.HeaderParseError: token, value = get_atom(value) + if value and value[0] == '@': + raise errors.HeaderParseError('Invalid Domain') if leader is not None: token[:0] = [leader] domain.append(token) diff --git a/Lib/email/_parseaddr.py b/Lib/email/_parseaddr.py index cdfa3729adc79e..41ff6f8c000d57 100644 --- a/Lib/email/_parseaddr.py +++ b/Lib/email/_parseaddr.py @@ -379,7 +379,12 @@ def getaddrspec(self): aslist.append('@') self.pos += 1 self.gotonext() - return EMPTYSTRING.join(aslist) + self.getdomain() + domain = self.getdomain() + if not domain: + # Invalid domain, return an empty address instead of returning a + # local part to denote failed parsing. + return EMPTYSTRING + return EMPTYSTRING.join(aslist) + domain def getdomain(self): """Get the complete domain name from an address.""" @@ -394,6 +399,10 @@ def getdomain(self): elif self.field[self.pos] == '.': self.pos += 1 sdlist.append('.') + elif self.field[self.pos] == '@': + # bpo-34155: Don't parse domains with two `@` like + # `a@malicious.org@important.com`. + return EMPTYSTRING elif self.field[self.pos] in self.atomends: break else: diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py index 9e862feab10c9e..0f19f8bcc2e0fa 100644 --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -1448,6 +1448,16 @@ def test_get_addr_spec_dot_atom(self): self.assertEqual(addr_spec.domain, 'example.com') self.assertEqual(addr_spec.addr_spec, 'star.a.star@example.com') + def test_get_addr_spec_multiple_domains(self): + with self.assertRaises(errors.HeaderParseError): + parser.get_addr_spec('star@a.star@example.com') + + with self.assertRaises(errors.HeaderParseError): + parser.get_addr_spec('star@a@example.com') + + with self.assertRaises(errors.HeaderParseError): + parser.get_addr_spec('star@172.17.0.1@example.com') + # get_obs_route def test_get_obs_route_simple(self): diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py index c29cc56203b1f7..aa775881c5521a 100644 --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -3041,6 +3041,20 @@ def test_parseaddr_empty(self): self.assertEqual(utils.parseaddr('<>'), ('', '')) self.assertEqual(utils.formataddr(utils.parseaddr('<>')), '') + def test_parseaddr_multiple_domains(self): + self.assertEqual( + utils.parseaddr('a@b@c'), + ('', '') + ) + self.assertEqual( + utils.parseaddr('a@b.c@c'), + ('', '') + ) + self.assertEqual( + utils.parseaddr('a@172.17.0.1@c'), + ('', '') + ) + def test_noquote_dump(self): self.assertEqual( utils.formataddr(('A Silly Person', 'person@dom.ain')), diff --git a/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst b/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst new file mode 100644 index 00000000000000..50292e29ed1d2f --- /dev/null +++ b/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst @@ -0,0 +1 @@ +Fix parsing of invalid email addresses with more than one ``@`` (e.g. a@b@c.com.) to not return the part before 2nd ``@`` as valid email address. Patch by maxking & jpic. pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy