summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBert JW Regeer <xistence@0x58.com>2016-01-03 00:48:53 -0700
committerBert JW Regeer <xistence@0x58.com>2016-01-03 00:48:53 -0700
commit7210c6048770d90089219db553eb968c64a60b42 (patch)
treee6d90dcb3b4aac4b7caa8b58ff5ab09e04ba043b
parent31fa39641ec259a61eb344d493470533f6ff0071 (diff)
parent260b9daecbffdb61aca06b35213234f21acfbf5d (diff)
downloadwaitress-7210c6048770d90089219db553eb968c64a60b42.tar.gz
Merge pull request #121 from Pylons/feature/header_seatbelt
Disallow control characters (\n\r) in start_response's headers
-rw-r--r--CHANGES.txt5
-rw-r--r--waitress/task.py4
-rw-r--r--waitress/tests/test_task.py7
3 files changed, 16 insertions, 0 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 4f50e50..71e4567 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,6 +1,11 @@
Next release
------------
+- Waitress will no longer accept headers with newline/carriage returns in them,
+ thereby disallowing HTTP Response Splitting. See
+ https://github.com/Pylons/waitress/issues/117 for more information, as well
+ as https://www.owasp.org/index.php/HTTP_Response_Splitting.
+
- Call prune() on the output buffer at the end of a request so that it doesn't
continue to grow without bounds. See
https://github.com/Pylons/waitress/issues/111 for more information.
diff --git a/waitress/task.py b/waitress/task.py
index 7136c32..501547a 100644
--- a/waitress/task.py
+++ b/waitress/task.py
@@ -371,6 +371,10 @@ class WSGITask(Task):
raise AssertionError(
'Header value %r is not a string in %r' % (v, (k, v))
)
+
+ if '\n' in v or '\r' in v:
+ raise ValueError("carriage return/line "
+ "feed character present in header value")
kl = k.lower()
if kl == 'content-length':
self.content_length = int(v)
diff --git a/waitress/tests/test_task.py b/waitress/tests/test_task.py
index 6d6fcce..c836f69 100644
--- a/waitress/tests/test_task.py
+++ b/waitress/tests/test_task.py
@@ -409,6 +409,13 @@ class TestWSGITask(unittest.TestCase):
inst.channel.server.application = app
self.assertRaises(AssertionError, inst.execute)
+ def test_execute_bad_header_value_control_characters(self):
+ def app(environ, start_response):
+ start_response('200 OK', [('a', '\n')])
+ inst = self._makeOne()
+ inst.channel.server.application = app
+ self.assertRaises(ValueError, inst.execute)
+
def test_preserve_header_value_order(self):
def app(environ, start_response):
write = start_response('200 OK', [('C', 'b'), ('A', 'b'), ('A', 'a')])