Cheroot cannot send a 400 response for requests with invalid chunked message bodies
❓ I'm submitting a ...
- [X] 🐞 bug report
- [ ] 🐣 feature request
- [ ] ❓ question about the decisions made in the repository
🐞 Describe the bug. What is the current behavior?
When a Cheroot-based WSGI server receives a request with an invalid chunked message body, it raises an exception upon attempting to access environ["wsgi.input"]. Unless I'm mistaken, the issue with this approach is twofold:
- If
environ["wsgi.input"]is never accessed, then the second request in a pipeline is assumed to be immediately following the end of headers of the first request. This leads to framing problems. - There is no graceful way to handle invalid chunked message bodies. A Cheroot-based server will either
- Respond 500 (i.e., not catch the exception) when 400 would have been more appropriate, or
- Explicitly respond 400, in which case the connection is not closed, and further requests will attempt to be parsed off the connection. This leads to framing problems.
❓ What is the motivation / use case for changing the behavior? Prevention of request smuggling.
💡 To Reproduce Steps to reproduce the behavior:
- Start a Cheroot-Based WSGI server that accesses
wsgi.inputoutside of atryblock. - Send it the following:
POST / HTTP/1.1\r\n
Host: a\r\n
Transfer-Encoding: chunked\r\n
\r\n
0 abc\r\n
\r\n
GET / HTTP/1.1\r\n
Host: a\r\n
\r\n
- Observe that it 500s.
- Add a
tryblock around the access towsgi.input, and respond 400 in theexceptblock. - Observe that the server responds 400 (as expected), but then responds 200 to the second request, even though a 400 should have caused the connection to be closed.
💡 Expected behavior Requests with invalid chunked message bodies should get 400s.
📋 Environment
- Cheroot version: main (1ff20b18e98e424e0616654c28c92524deef348a)
- Python version: 3.11.9
- OS: Linux 6.9.1
Other WSGI servers either automatically close the connection upon receipt of requests with invalid chunked message bodies (Waitress, Tornado) or close the connection automatically when a 400 response is sent manually (gunicorn).