-
-
Notifications
You must be signed in to change notification settings - Fork 32k
gh-127794: Validate header name according to rfc-5322 #127820
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
Changes from 27 commits
901a91c
5be0eaa
6ae6273
a7d1c0c
d04c9a2
bcab963
53bdb4f
31e4f3e
fae3664
026f35b
8f6f6c3
ce18c9b
aaa8879
fb73967
1de4e4c
b29f1aa
075a44a
d1b07c5
8129d13
5e371cc
84d2aec
ebd47a4
541f59b
3ac53da
4882f44
9726c21
d6549a0
44985a4
c83b6bf
d0256e6
6f3f0d4
efdc31f
dd5fcc0
2fade09
e521e71
6853c1c
07eb113
6e55b1b
d28ddba
08c1491
356306e
9c87b55
9afb5d8
a548261
35fd9ed
77175aa
e803dea
952fc1f
6ef3119
4aa1b13
867ddb4
349b5ec
8d4f62d
37e6e64
3e44493
6aba8e0
405782e
2ad5c8f
6331c05
a813023
b7bfacb
3ce49be
7038404
32dc6c8
151e146
810f9cb
079dda7
f69394e
e45165f
8233e92
2550011
31edff1
56a77e9
f2bbb92
98e5920
9dfe0f1
cf1f908
d5c538f
bf72d24
590c1ac
958bcf3
5f9d4a1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
""" | ||
|
||
import abc | ||
import re | ||
from email import header | ||
from email import charset as _charset | ||
from email.utils import _has_surrogates | ||
|
@@ -14,6 +15,12 @@ | |
'compat32', | ||
] | ||
|
||
valid_header_name_re = re.compile("[\041-\071\073-\176]+$") | ||
|
||
def validate_header_name(name): | ||
bitdancer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# Validate header name according to RFC 5322 | ||
if not valid_header_name_re.match(name): | ||
raise ValueError(f"Header field name contains invalid characters: {name!r}") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wrap <80, please |
||
|
||
class _PolicyBase: | ||
|
||
|
@@ -314,6 +321,7 @@ def header_store_parse(self, name, value): | |
"""+ | ||
The name and value are returned unmodified. | ||
""" | ||
validate_header_name(name) | ||
return (name, value) | ||
|
||
def header_fetch_parse(self, name, value): | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1004,6 +1004,32 @@ def test_folding_with_long_nospace_http_policy_1(self): | |
parsed_msg = message_from_bytes(m.as_bytes(), policy=policy.default) | ||
self.assertEqual(parsed_msg['Message-ID'], m['Message-ID']) | ||
|
||
def test_invalid_header_names(self): | ||
invalid_headers = [ | ||
('Invalid Header', 'contains space'), | ||
('Tab\tHeader', 'contains tab'), | ||
('Colon:Header', 'contains colon'), | ||
('', 'Empty name'), | ||
(' LeadingSpace', 'starts with space'), | ||
('TrailingSpace ', 'ends with space'), | ||
('Header\x7F', 'Non-ASCII character'), | ||
('Header\x80', 'Extended ASCII'), | ||
] | ||
for thispolicy in (policy.default, policy.compat32): | ||
picnixz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
for method in ('__setitem__', 'add_header'): | ||
for name, value in invalid_headers: | ||
with self.subTest( | ||
name=name, | ||
description=value, | ||
policy=thispolicy.__class__.__name__, | ||
method=method, | ||
): | ||
with self.assertRaises(ValueError) as cm: | ||
getattr(EmailMessage(policy=thispolicy), method)(name, value) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please wrap <80 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In addition, avoid having multiple calls within the message = EmailMessage(policy=thispolicy)
method = getattr(message, method)
pattern = re.escape(...)
with self.assertRaisesRegex(ValueError, pattern) as cm:
method(name, value)
self.assertIn(repr(name), str(cm.exception)) |
||
msg = str(cm.exception) | ||
self.assertRegex( msg, '(?i)(?=.*invalid)(?=.*header)(?=.*name)') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please wrap <80 |
||
self.assertIn(f"{name!r}", msg) | ||
|
||
bitdancer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
def test_get_body_malformed(self): | ||
"""test for bpo-42892""" | ||
msg = textwrap.dedent("""\ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
The :meth:`email.message.Message.add_header` method now validates header | ||
field names according to :rfc:`5322` when headers are added via add_header | ||
or __setitem__ and raises a ValueError if they contain invalid characters. | ||
srinivasreddy marked this conversation as resolved.
Show resolved
Hide resolved
|
Uh oh!
There was an error while loading. Please reload this page.