Skip to content

Commit 50ceb41

Browse files
benediktjohannesblurb-it[bot]vstinner
committed
gh-144370: Disallow usage of control characters in status in wsgiref.handlers for security (#144371)
Disallow usage of control characters in status in wsgiref.handlers to prevent HTTP header injections. Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> Co-authored-by: Victor Stinner <vstinner@python.org> (cherry picked from commit d931725)
1 parent ba6eba5 commit 50ceb41

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
@@ -879,6 +879,25 @@ def write(self, b):
879879
self.assertIsNotNone(h.status)
880880
self.assertIsNotNone(h.environ)
881881

882+
def testRaisesControlCharacters(self):
883+
for c0 in control_characters_c0():
884+
with self.subTest(c0):
885+
base = BaseHandler()
886+
with self.assertRaises(ValueError):
887+
base.start_response(c0, [('x', 'y')])
888+
889+
base = BaseHandler()
890+
with self.assertRaises(ValueError):
891+
base.start_response('200 OK', [(c0, 'y')])
892+
893+
# HTAB (\x09) is allowed in header values, but not in names.
894+
base = BaseHandler()
895+
if c0 != "\t":
896+
with self.assertRaises(ValueError):
897+
base.start_response('200 OK', [('x', c0)])
898+
else:
899+
base.start_response('200 OK', [('x', c0)])
900+
882901

883902
if __name__ == "__main__":
884903
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

@@ -238,6 +238,8 @@ def start_response(self, status, headers,exc_info=None):
238238
self.status = status
239239
self.headers = self.headers_class(headers)
240240
status = self._convert_string_type(status, "Status")
241+
if _name_disallowed_re.search(status):
242+
raise ValueError("Control characters are not allowed in status")
241243
assert len(status)>=4,"Status must be at least 4 characters"
242244
assert status[:3].isdigit(), "Status message must begin w/3-digit code"
243245
assert status[3]==" ", "Status message must have a space after code"

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,7 @@ Wolfgang Langner
10061006
Detlef Lannert
10071007
Rémi Lapeyre
10081008
Soren Larsen
1009+
Seth Michael Larson
10091010
Amos Latteier
10101011
Piers Lauder
10111012
Ben Laurie
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)