https://github.com/python/cpython/commit/10cf7e2bf76171f7c3b050a9acd762320e00486b
commit: 10cf7e2bf76171f7c3b050a9acd762320e00486b
branch: 3.10
author: Victor Stinner <[email protected]>
committer: pablogsal <[email protected]>
date: 2026-05-17T11:33:20-07:00
summary:
[3.10] gh-144370: Disallow usage of control characters in status in
wsgiref.handlers for security (#144371) (#145673)
files:
A Misc/NEWS.d/next/Security/2026-01-31-21-56-54.gh-issue-144370.fp9m8t.rst
M Lib/test/test_wsgiref.py
M Lib/wsgiref/handlers.py
M Misc/ACKS
diff --git a/Lib/test/test_wsgiref.py b/Lib/test/test_wsgiref.py
index 7c6c72f6e81384..a2b07f6aa345d7 100644
--- a/Lib/test/test_wsgiref.py
+++ b/Lib/test/test_wsgiref.py
@@ -879,6 +879,25 @@ def write(self, b):
self.assertIsNotNone(h.status)
self.assertIsNotNone(h.environ)
+ def testRaisesControlCharacters(self):
+ for c0 in control_characters_c0():
+ with self.subTest(c0):
+ base = BaseHandler()
+ with self.assertRaises(ValueError):
+ base.start_response(c0, [('x', 'y')])
+
+ base = BaseHandler()
+ with self.assertRaises(ValueError):
+ base.start_response('200 OK', [(c0, 'y')])
+
+ # HTAB (\x09) is allowed in header values, but not in names.
+ base = BaseHandler()
+ if c0 != "\t":
+ with self.assertRaises(ValueError):
+ base.start_response('200 OK', [('x', c0)])
+ else:
+ base.start_response('200 OK', [('x', c0)])
+
if __name__ == "__main__":
unittest.main()
diff --git a/Lib/wsgiref/handlers.py b/Lib/wsgiref/handlers.py
index 31360e58785ac6..df30af39293d2c 100644
--- a/Lib/wsgiref/handlers.py
+++ b/Lib/wsgiref/handlers.py
@@ -1,7 +1,7 @@
"""Base classes for server/gateway implementations"""
from .util import FileWrapper, guess_scheme, is_hop_by_hop
-from .headers import Headers
+from .headers import Headers, _name_disallowed_re
import sys, os, time
@@ -238,6 +238,8 @@ def start_response(self, status, headers,exc_info=None):
self.status = status
self.headers = self.headers_class(headers)
status = self._convert_string_type(status, "Status")
+ if _name_disallowed_re.search(status):
+ raise ValueError("Control characters are not allowed in status")
assert len(status)>=4,"Status must be at least 4 characters"
assert status[:3].isdigit(), "Status message must begin w/3-digit code"
assert status[3]==" ", "Status message must have a space after code"
diff --git a/Misc/ACKS b/Misc/ACKS
index 8483e110508889..9c28337a4b4343 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1006,6 +1006,7 @@ Wolfgang Langner
Detlef Lannert
Rémi Lapeyre
Soren Larsen
+Seth Michael Larson
Amos Latteier
Piers Lauder
Ben Laurie
diff --git
a/Misc/NEWS.d/next/Security/2026-01-31-21-56-54.gh-issue-144370.fp9m8t.rst
b/Misc/NEWS.d/next/Security/2026-01-31-21-56-54.gh-issue-144370.fp9m8t.rst
new file mode 100644
index 00000000000000..2d13a0611322c5
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2026-01-31-21-56-54.gh-issue-144370.fp9m8t.rst
@@ -0,0 +1,2 @@
+Disallow usage of control characters in status in :mod:`wsgiref.handlers` to
prevent HTTP header injections.
+Patch by Benedikt Johannes.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]