diff --git a/Lib/email/utils.py b/Lib/email/utils.py index d4824dc3601b2dd..c61d1f0ea6145f8 100644 --- a/Lib/email/utils.py +++ b/Lib/email/utils.py @@ -83,6 +83,8 @@ def formataddr(pair, charset='utf-8'): 'utf-8'. """ name, address = pair + if '\r' in address or '\n' in address or (name and ('\r' in name or '\n' in name)): + raise ValueError("invalid arguments; address parts cannot contain CR or LF") # The address MUST (per RFC) be ascii, so raise a UnicodeError if it isn't. address.encode('ascii') if name: diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py index d2c2261edbe04e1..90f50247c3360a1 100644 --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -3277,6 +3277,19 @@ def test_unicode_address_raises_error(self): self.assertRaises(UnicodeError, utils.formataddr, (None, addr)) self.assertRaises(UnicodeError, utils.formataddr, ("Name", addr)) + def test_crlf_in_parts_raises_error(self): + # formataddr() must reject CR and LF in either part so that the + # returned header value cannot be used to inject extra headers, + # matching email.headerregistry.Address. + for name, addr in [ + ('Real\rName', 'person@dom.ain'), + ('Real\nName', 'person@dom.ain'), + ('Real Name', 'person@dom.ain\r\nBcc: victim@dom.ain'), + ('Real Name', 'person@dom.ain\nSubject: spoofed'), + ]: + with self.subTest(name=name, addr=addr): + self.assertRaises(ValueError, utils.formataddr, (name, addr)) + def test_name_with_dot(self): x = 'John X. Doe ' y = '"John X. Doe" ' diff --git a/Misc/NEWS.d/next/Security/2026-05-26-19-30-00.gh-issue-150479.Kq7Lm2.rst b/Misc/NEWS.d/next/Security/2026-05-26-19-30-00.gh-issue-150479.Kq7Lm2.rst new file mode 100644 index 000000000000000..77009cec1d424fa --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-05-26-19-30-00.gh-issue-150479.Kq7Lm2.rst @@ -0,0 +1,3 @@ +:func:`email.utils.formataddr` now raises :exc:`ValueError` when the name or +address contains a carriage return or line feed, preventing header injection +and matching :class:`email.headerregistry.Address`.