-
-
Notifications
You must be signed in to change notification settings - Fork 29.4k
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
[CVE-2023-27043] gh-102988: Reject malformed addresses in email.parseaddr() #111116
Conversation
|
@gpshead @serhiy-storchaka @bitdancer @warsaw: Would you mind to review this security fix? See issue gh-102988 for the context. This PR is a copy of PR #108250 but I added strict=True parameter, so it's possible to get the old behavior. I added tests on both modes, strict=True and strict=False. |
My colleague Lumir Balhar @frenzymadness ran an impact check of PR #108250 on Fedora: in short, there is no impact, the test suite of all Python packages (in Fedora) pass with the change. While there were some build errors, they were unrelated to the email issue. For details, see https://copr.fedorainfracloud.org/coprs/lbalhar/email-CVE/builds/ COPR which as more than 4300 builds. Now with an additional strict parameter, if there is any impacted project, at least there is a way to "opt out". |
|
@tdwyer: Would you mind to review my change, to see if I preserved your work correctly? (code and tests) |
|
I think that we should backport the change to all branches accepting security fixes. Problem: the change refer to version numbers, which as |
|
@ambv @SethMichaelLarson: Would you mind to review this PR? |
|
Why is this a separate PR from #108250? |
Doc/whatsnew/3.13.rst
Outdated
| @@ -165,7 +165,7 @@ email | |||
| encountered instead of potentially inaccurate values. Add optional *strict* | |||
| parameter to these two functions: use ``strict=False`` to get the old | |||
| behavior, accept malformed inputs. | |||
| (Contributed by Thomas Dwyer for :gh:`102988` to ameliorate CVE-2023-27043 | |||
| (Contributed by Thomas Dwyer for :gh:`102988` to improve the CVE-2023-27043 | |||
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.
TIL a new word.
Lib/email/utils.py
Outdated
| @@ -42,6 +42,8 @@ | |||
|
|
|||
| specialsre = re.compile(r'[][\\()<>@,:;".]') | |||
| escapesre = re.compile(r'[\\"]') | |||
| realname_comma_re = re.compile(r'"[^"]*,[^"]*"') | |||
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.
| realname_comma_re = re.compile(r'"[^"]*,[^"]*"') | |
| realname_comma_re = re.compile(r'"[^",]*+,[^"]*+"') |
It is faster. But I am not sure that the use of such regex is correct.
Lib/email/utils.py
Outdated
| def _pre_parse_validation(email_header_fields): | ||
| accepted_values = [] | ||
| for v in email_header_fields: | ||
| s = v.replace('\\(', '').replace('\\)', '') |
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.
But what if that backslash was already escaped with a backslash? For example \\) or \\\\).
I'm not the author of the other PR. I copied the other PR and added strict parameter. |
|
I'm not the author of this PR and I was able to make commits to it. |
I don't feel comfortable to make significant change of a PR without asking the author. I prefer to create a separated PR and ask for review. |
|
Is this behavior a bug or a feature? I don't know how |
Oh. getaddresses() expects a sequence, not a string :-) |
|
Except of The latest major change was done in... 1997 with commit be7c45e
The latest minor change was done in 2019 to fix CVE-2019-16056: commit 8cb65d1 of issue #78336. |
Oh, realname_comma_re replaces |
|
Email addresses have multiple standards:
|
…n email.parseaddr() (python#111116) Detect email address parsing errors and return empty tuple to indicate the parsing error (old API). Add an optional 'strict' parameter to getaddresses() and parseaddr() functions. Patch by Thomas Dwyer. Co-Authored-By: Thomas Dwyer <github@tomd.tel> Changes for Python 2: - Define encoding for test_email - Adjust import so we don't need change the tests - Do not use f-strings - Do not use SubTest - KW only function arguments are not supported
…n email.parseaddr() (python#111116) Detect email address parsing errors and return empty tuple to indicate the parsing error (old API). Add an optional 'strict' parameter to getaddresses() and parseaddr() functions. Patch by Thomas Dwyer. Co-Authored-By: Thomas Dwyer <github@tomd.tel> Changes for Python 2: - Define encoding for test_email - Adjust import so we don't need change the tests - Do not use f-strings - Do not use SubTest - KW only function arguments are not supported
|
Thank you @vstinner for picking this up and helping to get this patch merged. I agree, adding a flag to disable the new strict behavior is a good idea to avoid any issues it may cause for others. |
…n email.parseaddr() (python#111116) Detect email address parsing errors and return empty tuple to indicate the parsing error (old API). Add an optional 'strict' parameter to getaddresses() and parseaddr() functions. Patch by Thomas Dwyer. Co-Authored-By: Thomas Dwyer <github@tomd.tel>
…n email.parseaddr() (python#111116) Detect email address parsing errors and return empty tuple to indicate the parsing error (old API). Add an optional 'strict' parameter to getaddresses() and parseaddr() functions. Patch by Thomas Dwyer. Co-Authored-By: Thomas Dwyer <github@tomd.tel>
….parseaddr() (python#111116) Detect email address parsing errors and return empty tuple to indicate the parsing error (old API). Add an optional 'strict' parameter to getaddresses() and parseaddr() functions. Patch by Thomas Dwyer. Co-Authored-By: Thomas Dwyer <github@tomd.tel>
…n email.parseaddr() (python#111116) Detect email address parsing errors and return empty tuple to indicate the parsing error (old API). Add an optional 'strict' parameter to getaddresses() and parseaddr() functions. Patch by Thomas Dwyer. Co-Authored-By: Thomas Dwyer <github@tomd.tel>
…n email.parseaddr() (python#111116) Detect email address parsing errors and return empty tuple to indicate the parsing error (old API). Add an optional 'strict' parameter to getaddresses() and parseaddr() functions. Patch by Thomas Dwyer. Co-Authored-By: Thomas Dwyer <github@tomd.tel>
…n email.parseaddr() (python#111116) Detect email address parsing errors and return empty tuple to indicate the parsing error (old API). Add an optional 'strict' parameter to getaddresses() and parseaddr() functions. Patch by Thomas Dwyer. Co-Authored-By: Thomas Dwyer <github@tomd.tel>
…n email.parseaddr() (python#111116) Detect email address parsing errors and return empty tuple to indicate the parsing error (old API). Add an optional 'strict' parameter to getaddresses() and parseaddr() functions. Patch by Thomas Dwyer. Co-Authored-By: Thomas Dwyer <github@tomd.tel>
…n email.parseaddr() (python#111116) Detect email address parsing errors and return empty tuple to indicate the parsing error (old API). Add an optional 'strict' parameter to getaddresses() and parseaddr() functions. Patch by Thomas Dwyer. Co-Authored-By: Thomas Dwyer <github@tomd.tel>
…n email.parseaddr() (python#111116) Detect email address parsing errors and return empty tuple to indicate the parsing error (old API). Add an optional 'strict' parameter to getaddresses() and parseaddr() functions. Patch by Thomas Dwyer. Co-Authored-By: Thomas Dwyer <github@tomd.tel>
…n email.parseaddr() (python#111116) Detect email address parsing errors and return empty tuple to indicate the parsing error (old API). Add an optional 'strict' parameter to getaddresses() and parseaddr() functions. Patch by Thomas Dwyer. Co-Authored-By: Thomas Dwyer <github@tomd.tel>
…n email.parseaddr() (python#111116) Detect email address parsing errors and return empty tuple to indicate the parsing error (old API). Add an optional 'strict' parameter to getaddresses() and parseaddr() functions. Patch by Thomas Dwyer. Co-Authored-By: Thomas Dwyer <github@tomd.tel>
…n email.parseaddr() (python#111116) Detect email address parsing errors and return empty tuple to indicate the parsing error (old API). Add an optional 'strict' parameter to getaddresses() and parseaddr() functions. Patch by Thomas Dwyer. Co-Authored-By: Thomas Dwyer <github@tomd.tel>
…n email.parseaddr() (python#111116) Detect email address parsing errors and return empty tuple to indicate the parsing error (old API). Add an optional 'strict' parameter to getaddresses() and parseaddr() functions. Patch by Thomas Dwyer. Co-Authored-By: Thomas Dwyer <github@tomd.tel>
…n email.parseaddr() (python#111116) Detect email address parsing errors and return empty tuple to indicate the parsing error (old API). Add an optional 'strict' parameter to getaddresses() and parseaddr() functions. Patch by Thomas Dwyer. Co-Authored-By: Thomas Dwyer <github@tomd.tel>
…n email.parseaddr() (python#111116) Detect email address parsing errors and return empty tuple to indicate the parsing error (old API). Add an optional 'strict' parameter to getaddresses() and parseaddr() functions. Patch by Thomas Dwyer. Co-Authored-By: Thomas Dwyer <github@tomd.tel>
…n email.parseaddr() (python#111116) Detect email address parsing errors and return empty tuple to indicate the parsing error (old API). Add an optional 'strict' parameter to getaddresses() and parseaddr() functions. Patch by Thomas Dwyer. Co-Authored-By: Thomas Dwyer <github@tomd.tel>
…n email.parseaddr() (python#111116) Detect email address parsing errors and return empty tuple to indicate the parsing error (old API). Add an optional 'strict' parameter to getaddresses() and parseaddr() functions. Patch by Thomas Dwyer. Co-Authored-By: Thomas Dwyer <github@tomd.tel>
…n email.parseaddr() (python#111116) Detect email address parsing errors and return empty tuple to indicate the parsing error (old API). Add an optional 'strict' parameter to getaddresses() and parseaddr() functions. Patch by Thomas Dwyer. Co-Authored-By: Thomas Dwyer <github@tomd.tel>
…n email.parseaddr() (python#111116) Detect email address parsing errors and return empty tuple to indicate the parsing error (old API). Add an optional 'strict' parameter to getaddresses() and parseaddr() functions. Patch by Thomas Dwyer. Co-Authored-By: Thomas Dwyer <github@tomd.tel>
|
I have already some testing on this backport of the patch for Python 2.7. Comments and reviews are more than welcome. |
Hey @mcepl . We have already backported this to python2.7 in Fedora: fedora-python@5ae7bab |
|
Is it time to backport the change to Python 3.8-3.12? So far, nobody reported any regression in Python 3.13. |
Of course, I am eager for reviews and comments. So far, the only issue I have heard about was confusion about Also, I left some comments on that commit. |
According to this comment, not yet: #102988 (comment) |
…n email.parseaddr() (python#111116) Detect email address parsing errors and return empty tuple to indicate the parsing error (old API). Add an optional 'strict' parameter to getaddresses() and parseaddr() functions. Patch by Thomas Dwyer. Co-Authored-By: Thomas Dwyer <github@tomd.tel>
Detect email address parsing errors and return empty tuple to indicate the parsing error (old API). Add an optional 'strict' parameter to getaddresses() and parseaddr() functions. Patch by Thomas Dwyer.
📚 Documentation preview 📚: https://cpython-previews--111116.org.readthedocs.build/