GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — [CVE-2025-11468] email preserve parens when folding comments · openSUSE-Python/cpython@632a40d

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
  • Lib
    • email
      • _header_value_parser.py
    • test/test_email
      • test__header_value_parser.py
  • Misc/NEWS.d/next/Security
    • 2026-01-16-14-40-31.gh-issue-143935.U2YtKl.rst
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎Lib/email/_header_value_parser.py‎

Copy file name to clipboardExpand all lines: Lib/email/_header_value_parser.py
+23-1Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,12 @@
9696
NLSET = {'\n', '\r'}
9797
SPECIALSNL = SPECIALS | NLSET
9898

99+
def make_parenthesis_pairs(value):
100+
"""Escape parenthesis and backslash for use within a comment."""
101+
return str(value).replace('\\', '\\\\') \
102+
.replace('(', '\\(').replace(')', '\\)')
103+
104+
99105
def quote_string(value):
100106
return '"'+str(value).replace('\\', '\\\\').replace('"', r'\"')+'"'
101107

@@ -931,7 +937,7 @@ def value(self):
931937
return ' '
932938

933939
def startswith_fws(self):
934-
return True
940+
return self and self[0] in WSP
935941

936942

937943
class ValueTerminal(Terminal):
@@ -2861,6 +2867,22 @@ def _refold_parse_tree(parse_tree, *, policy):
28612867
if not hasattr(part, 'encode'):
28622868
# It's not a terminal, try folding the subparts.
28632869
newparts = list(part)
2870+
if part.token_type == 'bare-quoted-string':
2871+
# To fold a quoted string we need to create a list of terminal
2872+
# tokens that will render the leading and trailing quotes
2873+
# and use quoted pairs in the value as appropriate.
2874+
newparts = (
2875+
[ValueTerminal('"', 'ptext')] +
2876+
[ValueTerminal(make_quoted_pairs(p), 'ptext')
2877+
for p in newparts] +
2878+
[ValueTerminal('"', 'ptext')])
2879+
if part.token_type == 'comment':
2880+
newparts = (
2881+
[ValueTerminal('(', 'ptext')] +
2882+
[ValueTerminal(make_parenthesis_pairs(p), 'ptext')
2883+
if p.token_type == 'ptext' else p
2884+
for p in newparts] +
2885+
[ValueTerminal(')', 'ptext')])
28642886
if not part.as_ew_allowed:
28652887
wrap_as_ew_blocked += 1
28662888
newparts.append(end_ew_not_allowed)
Collapse file

‎Lib/test/test_email/test__header_value_parser.py‎

Copy file name to clipboardExpand all lines: Lib/test/test_email/test__header_value_parser.py
+23Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2751,6 +2751,29 @@ def test_address_list_with_unicode_names_in_quotes(self):
27512751
'=?utf-8?q?H=C3=BCbsch?= Kaktus <[email protected]>,\n'
27522752
' =?utf-8?q?bei=C3=9Ft_bei=C3=9Ft?= <[email protected]>\n')
27532753

2754+
def test_address_list_with_long_unwrapable_comment(self):
2755+
policy = self.policy.clone(max_line_length=40)
2756+
cases = [
2757+
# (to, folded)
2758+
('(loremipsumdolorsitametconsecteturadipi)<[email protected]>',
2759+
'(loremipsumdolorsitametconsecteturadipi)<[email protected]>\n'),
2760+
('<[email protected]>(loremipsumdolorsitametconsecteturadipi)',
2761+
'<[email protected]>(loremipsumdolorsitametconsecteturadipi)\n'),
2762+
('(loremipsum dolorsitametconsecteturadipi)<[email protected]>',
2763+
'(loremipsum dolorsitametconsecteturadipi)<[email protected]>\n'),
2764+
('<[email protected]>(loremipsum dolorsitametconsecteturadipi)',
2765+
'<[email protected]>(loremipsum\n dolorsitametconsecteturadipi)\n'),
2766+
('(Escaped \\( \\) chars \\\\ in comments stay escaped)<[email protected]>',
2767+
'(Escaped \\( \\) chars \\\\ in comments stay\n escaped)<[email protected]>\n'),
2768+
('((loremipsum)(loremipsum)(loremipsum)(loremipsum))<[email protected]>',
2769+
'((loremipsum)(loremipsum)(loremipsum)(loremipsum))<[email protected]>\n'),
2770+
('((loremipsum)(loremipsum)(loremipsum) (loremipsum))<[email protected]>',
2771+
'((loremipsum)(loremipsum)(loremipsum)\n (loremipsum))<[email protected]>\n'),
2772+
]
2773+
for (to, folded) in cases:
2774+
with self.subTest(to=to):
2775+
self._test(parser.get_address_list(to)[0], folded, policy=policy)
2776+
27542777
# XXX Need tests with comments on various sides of a unicode token,
27552778
# and with unicode tokens in the comments. Spaces inside the quotes
27562779
# currently don't do the right thing.
Collapse file

‎Misc/NEWS.d/next/Security/2026-01-16-14-40-31.gh-issue-143935.U2YtKl.rst‎

Copy file name to clipboard
+6Lines changed: 6 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Fixed a bug in the folding of comments when flattening an email message
2+
using a modern email policy. Comments consisting of a very long sequence of
3+
non-foldable characters could trigger a forced line wrap that omitted the
4+
required leading space on the continuation line, causing the remainder of
5+
the comment to be interpreted as a new header field. This enabled header
6+
injection with carefully crafted inputs.

0 commit comments

Comments
0 (0)
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.