Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 34k
gh-102988: Detect email address parsing errors and return empty tuple to indicate the parsing error (old API)#105127
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Uh oh!
There was an error while loading. Please reload this page.
Merged
Changes from all commits
Commits
Show all changes
9 commits Select commit Hold shift + click to select a range
81098ed gh-102988: Detect email address parsing errors and return empty tuple…
tdwyer ecbb31c r-prefix strs with \ in the tests
gpshead d8d2831 reword getaddresses docstring
gpshead b44a0b7 Update comment for getaddresses() and fix broken email test
tdwyer 40002d9 Add NEWS
tdwyer 86ffb57 Merge branch 'main' into fix_issues102988
gpshead 302ee76 Fix NEWS entry. It was not a Module its Class email._parseaddr.Addres…
tdwyer 48d9f58 Add email.utils docs, narrow the docstring.
gpshead f96a3ff Add versionchanged to parseaddr, add What's New.
gpshead File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -65,6 +65,11 @@ of the new API. | ||
| *email address* parts. Returns a tuple of that information, unless the parse | ||
| fails, in which case a 2-tuple of ``('', '')`` is returned. | ||
| .. versionchanged:: 3.12 | ||
| For security reasons, addresses that were ambiguous and could parse into | ||
| multiple different addresses now cause ``('', '')`` to be returned | ||
| instead of only one of the *potential* addresses. | ||
| .. function:: formataddr(pair, charset='utf-8') | ||
| @@ -87,7 +92,7 @@ of the new API. | ||
| This method returns a list of 2-tuples of the form returned by ``parseaddr()``. | ||
| *fieldvalues* is a sequence of header field values as might be returned by | ||
| :meth:`Message.get_all <email.message.Message.get_all>`. Here's a simple | ||
| example that gets all the recipients of a message:: | ||
| example that gets all the recipients of a message: | ||
| from email.utils import getaddresses | ||
| @@ -97,6 +102,25 @@ of the new API. | ||
| resent_ccs = msg.get_all('resent-cc', []) | ||
| all_recipients = getaddresses(tos + ccs + resent_tos + resent_ccs) | ||
| When parsing fails for a single fieldvalue, a 2-tuple of ``('', '')`` | ||
| is returned in its place. Other errors in parsing the list of | ||
| addresses such as a fieldvalue seemingly parsing into multiple | ||
| addresses may result in a list containing a single empty 2-tuple | ||
| ``[('', '')]`` being returned rather than returning potentially | ||
| invalid output. | ||
| Example malformed input parsing: | ||
| .. doctest:: | ||
| >>> from email.utils import getaddresses | ||
| >>> getaddresses(['[email protected] <[email protected]>', '[email protected]']) | ||
| [('', '')] | ||
| .. versionchanged:: 3.12 | ||
| The 2-tuple of ``('', '')`` in the returned values when parsing | ||
| fails were added as to address a security issue. | ||
| .. function:: parsedate(date) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -3319,15 +3319,90 @@ def test_getaddresses(self): | ||
| [('Al Person', '[email protected]'), | ||
| ('Bud Person', '[email protected]')]) | ||
| def test_getaddresses_parsing_errors(self): | ||
| """Test for parsing errors from CVE-2023-27043""" | ||
| eq = self.assertEqual | ||
| eq(utils.getaddresses(['[email protected](<[email protected]>']), | ||
| [('', '')]) | ||
| eq(utils.getaddresses(['[email protected])<[email protected]>']), | ||
| [('', '')]) | ||
| eq(utils.getaddresses(['[email protected]<<[email protected]>']), | ||
| [('', '')]) | ||
| eq(utils.getaddresses(['[email protected]><[email protected]>']), | ||
| [('', '')]) | ||
| eq(utils.getaddresses(['[email protected]@<[email protected]>']), | ||
| [('', '')]) | ||
| eq(utils.getaddresses(['[email protected],<[email protected]>']), | ||
| [('', '[email protected]'), ('', '[email protected]')]) | ||
| eq(utils.getaddresses(['[email protected];<[email protected]>']), | ||
| [('', '')]) | ||
| eq(utils.getaddresses(['[email protected]:<[email protected]>']), | ||
| [('', '')]) | ||
| eq(utils.getaddresses(['[email protected].<[email protected]>']), | ||
| [('', '')]) | ||
| eq(utils.getaddresses(['[email protected]"<[email protected]>']), | ||
| [('', '')]) | ||
| eq(utils.getaddresses(['[email protected][<[email protected]>']), | ||
| [('', '')]) | ||
| eq(utils.getaddresses(['[email protected]]<[email protected]>']), | ||
| [('', '')]) | ||
| def test_parseaddr_parsing_errors(self): | ||
| """Test for parsing errors from CVE-2023-27043""" | ||
| eq = self.assertEqual | ||
| eq(utils.parseaddr(['[email protected](<[email protected]>']), | ||
| ('', '')) | ||
| eq(utils.parseaddr(['[email protected])<[email protected]>']), | ||
| ('', '')) | ||
| eq(utils.parseaddr(['[email protected]<<[email protected]>']), | ||
| ('', '')) | ||
| eq(utils.parseaddr(['[email protected]><[email protected]>']), | ||
| ('', '')) | ||
| eq(utils.parseaddr(['[email protected]@<[email protected]>']), | ||
| ('', '')) | ||
| eq(utils.parseaddr(['[email protected],<[email protected]>']), | ||
| ('', '')) | ||
| eq(utils.parseaddr(['[email protected];<[email protected]>']), | ||
| ('', '')) | ||
| eq(utils.parseaddr(['[email protected]:<[email protected]>']), | ||
| ('', '')) | ||
| eq(utils.parseaddr(['[email protected].<[email protected]>']), | ||
| ('', '')) | ||
| eq(utils.parseaddr(['[email protected]"<[email protected]>']), | ||
| ('', '')) | ||
| eq(utils.parseaddr(['[email protected][<[email protected]>']), | ||
| ('', '')) | ||
| eq(utils.parseaddr(['[email protected]]<[email protected]>']), | ||
| ('', '')) | ||
| def test_getaddresses_nasty(self): | ||
| eq = self.assertEqual | ||
| eq(utils.getaddresses(['foo: ;']), [('', '')]) | ||
| eq(utils.getaddresses( | ||
| ['[]*-- =~$']), | ||
| [('', ''), ('', ''), ('', '*--')]) | ||
| eq(utils.getaddresses(['[]*-- =~$']), [('', '')]) | ||
| eq(utils.getaddresses( | ||
| ['foo: ;', '"Jason R. Mastaler" <[email protected]>']), | ||
| [('', ''), ('Jason R. Mastaler', '[email protected]')]) | ||
| eq(utils.getaddresses( | ||
| [r'Pete(A nice \) chap) <pete(his account)@silly.test(his host)>']), | ||
| [('Pete (A nice ) chap his account his host)', '[email protected]')]) | ||
| eq(utils.getaddresses( | ||
| ['(Empty list)(start)Undisclosed recipients :(nobody(I know))']), | ||
| [('', '')]) | ||
| eq(utils.getaddresses( | ||
| ['Mary <@machine.tld:[email protected]>, , jdoe@test . example']), | ||
| [('Mary', '[email protected]'), ('', ''), ('', '[email protected]')]) | ||
| eq(utils.getaddresses( | ||
| ['John Doe <jdoe@machine(comment). example>']), | ||
| [('John Doe (comment)', '[email protected]')]) | ||
| eq(utils.getaddresses( | ||
| ['"Mary Smith: Personal Account" <[email protected]>']), | ||
| [('Mary Smith: Personal Account', '[email protected]')]) | ||
| eq(utils.getaddresses( | ||
| ['Undisclosed recipients:;']), | ||
| [('', '')]) | ||
| eq(utils.getaddresses( | ||
| [r'<[email protected]>, "Giant; \"Big\" Box" <[email protected]>']), | ||
| [('', '[email protected]'), ('Giant; "Big" Box', '[email protected]')]) | ||
| def test_getaddresses_embedded_comment(self): | ||
| """Test proper handling of a nested comment""" | ||
4 changes: 4 additions & 0 deletions 4 Misc/NEWS.d/next/Security/2023-06-13-20-52-24.gh-issue-102988.Kei7Vf.rst
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| CVE-2023-27043: Prevent :func:`email.utils.parseaddr` | ||
| and :func:`email.utils.getaddresses` from returning the realname portion of an | ||
| invalid RFC2822 email header in the email address portion of the 2-tuple | ||
| returned after being parsed by :class:`email._parseaddr.AddressList`. |
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tdwyer Is this right? Isn’t the next paragraph still a literal block? Why have you removed this colon?