GitHub

File tree

  • Lib

    • email

    • test/test_email

  • Misc/NEWS.d/next/Security

Original file line numberDiff line numberDiff line change

@@ -1566,6 +1566,8 @@ def get_domain(value):

15661566

token, value = get_dot_atom(value)

15671567

except errors.HeaderParseError:

15681568

token, value = get_atom(value)

1569+

if value and value[0] == '@':

1570+

raise errors.HeaderParseError('Invalid Domain')

15691571

if leader is not None:

15701572

token[:0] = [leader]

15711573

domain.append(token)

Original file line numberDiff line numberDiff line change

@@ -379,7 +379,12 @@ def getaddrspec(self):

379379

aslist.append('@')

380380

self.pos += 1

381381

self.gotonext()

382-

return EMPTYSTRING.join(aslist) + self.getdomain()

382+

domain = self.getdomain()

383+

if not domain:

384+

# Invalid domain, return an empty address instead of returning a

385+

# local part to denote failed parsing.

386+

return EMPTYSTRING

387+

return EMPTYSTRING.join(aslist) + domain

383388
384389

def getdomain(self):

385390

"""Get the complete domain name from an address."""

@@ -394,6 +399,10 @@ def getdomain(self):

394399

elif self.field[self.pos] == '.':

395400

self.pos += 1

396401

sdlist.append('.')

402+

elif self.field[self.pos] == '@':

403+

# bpo-34155: Don't parse domains with two `@` like

404+

# `a@malicious.org@important.com`.

405+

return EMPTYSTRING

397406

elif self.field[self.pos] in self.atomends:

398407

break

399408

else:

Original file line numberDiff line numberDiff line change

@@ -1428,6 +1428,16 @@ def test_get_addr_spec_dot_atom(self):

14281428

self.assertEqual(addr_spec.domain, 'example.com')

14291429

self.assertEqual(addr_spec.addr_spec, 'star.a.star@example.com')

14301430
1431+

def test_get_addr_spec_multiple_domains(self):

1432+

with self.assertRaises(errors.HeaderParseError):

1433+

parser.get_addr_spec('star@a.star@example.com')

1434+
1435+

with self.assertRaises(errors.HeaderParseError):

1436+

parser.get_addr_spec('star@a@example.com')

1437+
1438+

with self.assertRaises(errors.HeaderParseError):

1439+

parser.get_addr_spec('star@172.17.0.1@example.com')

1440+
14311441

# get_obs_route

14321442
14331443

def test_get_obs_route_simple(self):

Original file line numberDiff line numberDiff line change

@@ -3041,6 +3041,20 @@ def test_parseaddr_empty(self):

30413041

self.assertEqual(utils.parseaddr('<>'), ('', ''))

30423042

self.assertEqual(utils.formataddr(utils.parseaddr('<>')), '')

30433043
3044+

def test_parseaddr_multiple_domains(self):

3045+

self.assertEqual(

3046+

utils.parseaddr('a@b@c'),

3047+

('', '')

3048+

)

3049+

self.assertEqual(

3050+

utils.parseaddr('a@b.c@c'),

3051+

('', '')

3052+

)

3053+

self.assertEqual(

3054+

utils.parseaddr('a@172.17.0.1@c'),

3055+

('', '')

3056+

)

3057+
30443058

def test_noquote_dump(self):

30453059

self.assertEqual(

30463060

utils.formataddr(('A Silly Person', 'person@dom.ain')),

Original file line numberDiff line numberDiff line change

@@ -0,0 +1 @@

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.

Read the original on github.com ↗