GitHub

File tree

  • Lib

    • email

    • test/test_email

  • Misc/NEWS.d/next/Security

Original file line numberDiff line numberDiff line change

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

15611561

token, value = get_dot_atom(value)

15621562

except errors.HeaderParseError:

15631563

token, value = get_atom(value)

1564+

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

1565+

raise errors.HeaderParseError('Invalid Domain')

15641566

if leader is not None:

15651567

token[:0] = [leader]

15661568

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

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

14181418

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

14191419

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

14201420
1421+

def test_get_addr_spec_multiple_domains(self):

1422+

with self.assertRaises(errors.HeaderParseError):

1423+

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

1424+
1425+

with self.assertRaises(errors.HeaderParseError):

1426+

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

1427+
1428+

with self.assertRaises(errors.HeaderParseError):

1429+

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

1430+
14211431

# get_obs_route

14221432
14231433

def test_get_obs_route_simple(self):

Original file line numberDiff line numberDiff line change

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

30353035

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

30363036

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

30373037
3038+

def test_parseaddr_multiple_domains(self):

3039+

self.assertEqual(

3040+

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

3041+

('', '')

3042+

)

3043+

self.assertEqual(

3044+

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

3045+

('', '')

3046+

)

3047+

self.assertEqual(

3048+

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

3049+

('', '')

3050+

)

3051+
30383052

def test_noquote_dump(self):

30393053

self.assertEqual(

30403054

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 ↗