Skip to content

Commit 89b69db

Browse files
miss-islingtonbenediktjohannesblurb-it[bot]vstinner
authored
[3.14] gh-144370: Disallow usage of control characters in status in wsgiref.handlers for security (GH-144371) (#145586)
gh-144370: Disallow usage of control characters in status in wsgiref.handlers for security (GH-144371) Disallow usage of control characters in status in wsgiref.handlers to prevent HTTP header injections. (cherry picked from commit d931725) Co-authored-by: Benedikt Johannes <benedikt.johannes.hofer@gmail.com> Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> Co-authored-by: Victor Stinner <vstinner@python.org>
1 parent 3a7c897 commit 89b69db

File tree

4 files changed

+25
-1
lines changed

4 files changed

+25
-1
lines changed

Lib/test/test_wsgiref.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,25 @@ def write(self, b):
855855
self.assertIsNotNone(h.status)
856856
self.assertIsNotNone(h.environ)
857857

858+
def testRaisesControlCharacters(self):
859+
for c0 in control_characters_c0():
860+
with self.subTest(c0):
861+
base = BaseHandler()
862+
with self.assertRaises(ValueError):
863+
base.start_response(c0, [('x', 'y')])
864+
865+
base = BaseHandler()
866+
with self.assertRaises(ValueError):
867+
base.start_response('200 OK', [(c0, 'y')])
868+
869+
# HTAB (\x09) is allowed in header values, but not in names.
870+
base = BaseHandler()
871+
if c0 != "\t":
872+
with self.assertRaises(ValueError):
873+
base.start_response('200 OK', [('x', c0)])
874+
else:
875+
base.start_response('200 OK', [('x', c0)])
876+
858877

859878
if __name__ == "__main__":
860879
unittest.main()

Lib/wsgiref/handlers.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Base classes for server/gateway implementations"""
22

33
from .util import FileWrapper, guess_scheme, is_hop_by_hop
4-
from .headers import Headers
4+
from .headers import Headers, _name_disallowed_re
55

66
import sys, os, time
77

@@ -249,6 +249,8 @@ def start_response(self, status, headers,exc_info=None):
249249
return self.write
250250

251251
def _validate_status(self, status):
252+
if _name_disallowed_re.search(status):
253+
raise ValueError("Control characters are not allowed in status")
252254
if len(status) < 4:
253255
raise AssertionError("Status must be at least 4 characters")
254256
if not status[:3].isdigit():

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,7 @@ Wolfgang Langner
10711071
Detlef Lannert
10721072
Rémi Lapeyre
10731073
Soren Larsen
1074+
Seth Michael Larson
10741075
Amos Latteier
10751076
Keenan Lau
10761077
Piers Lauder
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Disallow usage of control characters in status in :mod:`wsgiref.handlers` to prevent HTTP header injections.
2+
Patch by Benedikt Johannes.

0 commit comments

Comments
 (0)