43 Commits

Author SHA1 Message Date
Benoit Chesneau
98eac0b04e chore: require gunicorn_h1c >=0.6.5 and drop last python_only marker
gunicorn_h1c 0.6.5 ships the Content-Length list-form rejection
(h1c #8). The last python_only marker can now come off
rfc9112_smuggle_cl_list_form_01.
2026-04-20 07:29:47 +02:00
Benoit Chesneau
408b1f0517 chore: require gunicorn_h1c >=0.6.4 and drop python_only markers
gunicorn_h1c 0.6.4 ships the RFC 9110/9112 hardening added in h1c #4,
#6, and #7: control chars in header values, request-target form/method
pairing, and forbidden trailer field-names. All the corresponding
fixtures now pass against the C parser, so their python_only markers
are removed.

The CL list form fixture stays marked — the C parser does not yet
reject Content-Length: "5, 5".
2026-04-19 23:40:58 +02:00
Benoit Chesneau
73e64364ca test: codify rejection of Content-Length list form (RFC 9112 section 6.3) 2026-04-19 20:49:32 +02:00
Benoit Chesneau
2391901b40 test: codify chunked size/extension edge cases (RFC 9112 section 7.1) 2026-04-19 13:21:20 +02:00
Benoit Chesneau
826bfc7e88 test: add failing fixtures for control chars in header value 2026-04-19 12:05:00 +02:00
Benoit Chesneau
3b3752eb90 test: add failing fixtures for forbidden trailer fields 2026-04-19 11:38:05 +02:00
Benoit Chesneau
62252223e0 test: codify rejection of relative-reference request-target (RFC 9112 section 3.2) 2026-04-19 11:23:00 +02:00
Benoit Chesneau
e7fd6a104f test: add failing fixture for authority-form with non-CONNECT method 2026-04-19 11:09:29 +02:00
Benoit Chesneau
82d33d4c71 fix: reject asterisk-form request-target outside OPTIONS (RFC 9112 section 3.2.4)
The Python WSGI and ASGI parsers both accepted `GET *` and similar; RFC
9112 restricts asterisk-form to OPTIONS. Both now raise InvalidRequestLine.

The fast (C) parser in gunicorn_h1c does not yet enforce this, so the
fixture is marked python_only via a new sidecar flag honored by the WSGI
and ASGI invalid-request harnesses.
2026-04-19 10:43:01 +02:00
Benoit Chesneau
2c57071675 test: add failing fixture for asterisk-form with non-OPTIONS method 2026-04-19 10:37:14 +02:00
Benoit Chesneau
f1c204626f test: codify RFC 9112 request-target and TE/CL vectors (phase 1)
Six treq fixtures covering gaps: absolute-form, asterisk-form (OPTIONS *),
authority-form (CONNECT), TE codings stacking (gzip/identity before chunked),
and the CL + TE:chunked smuggling vector.

Phase 1 of a staged corpus expansion; fixtures only, no parser changes.
2026-04-19 09:52:15 +02:00
Benoit Chesneau
8d08aaa2cb Fix --limit-request-line 0 to mean unlimited
Per documentation, limit_request_line=0 means unlimited. The code was
incorrectly treating 0 as "use default max" by checking <= 0 instead
of < 0.

For the fast C parser (gunicorn_h1c), which doesn't support 0 as
unlimited, pass a large value (1MB) instead. This applies to both
WSGI workers (http/message.py) and ASGI workers (asgi/protocol.py).

Fixes #3563
2026-03-26 23:42:14 +01:00
Benoit Chesneau
b00f125755 Integrate gunicorn_h1c 0.6.3 with InvalidChunkExtension support
Update to gunicorn_h1c >= 0.6.3 which adds InvalidChunkExtension
validation for rejecting chunk extensions with bare CR bytes per
RFC 9112.

Changes:
- Update pyproject.toml to require gunicorn_h1c >= 0.6.3
- Add InvalidChunkExtension exception to gunicorn/asgi/parser.py
- Handle InvalidChunkExtension from both Python and C parsers in protocol.py
- Add chunk extension validation tests
- Update treq.py badrequest class to support hex escapes
2026-03-26 15:46:51 +01:00
Benoit Chesneau
4ce6aa1f3e Fix limit handling and add default max limit tests
- LimitRequestLine now accepts optional max_size parameter
- Use default max limits when limit_request_line or limit_request_field_size is 0
- Add tests validating default max enforcement (8190 bytes)
- Handle alternate exceptions from fast parser in test_invalid_requests
2026-03-22 16:17:55 +01:00
Benoit Chesneau
95b7ffeeaa chore: prepare release 25.0.2
- Bump version to 25.0.2
- Update copyright year to 2026 in LICENSE and NOTICE
- Add license headers to all Python source files
- Add changelog entry for 25.0.2
2026-02-06 08:21:18 +01:00
Paul J. Dorn
2bc931e7d9 whitespace handling in header field values
Strip whitespace also *after* header field value.
Simply refuse obsolete header folding (a default-off
option to revert is temporarily provided).
While we are at it, explicitly handle recently
introduced http error classes with intended status code.
2024-08-07 19:42:16 +02:00
benoitc
555d2fa27f don't tolerate wrong te headers
changes:

- Just follow the new TE specification (https://datatracker.ietf.org/doc/html/rfc9112#name-transfer-encoding)
 here and accept to introduce a breaking change.
- gandle multiple TE on one line

** breaking changes ** : invalid  headers and position will now return
an error.
2024-08-06 23:47:01 +02:00
Benoit Chesneau
9a96e75808
Merge pull request #3253 from pajod/patch-rfc9110-section5.5
Refuse requests with invalid and dangerous CR/LF/NUL in header field value, as demanded by rfc9110 section 5.5
2024-08-06 22:25:12 +02:00
Paul J. Dorn
cabc666277 chunked encoding: example invalid requests 2024-07-31 19:21:07 +02:00
Paul J. Dorn
eda9d456d3 forbid lone CR/LF and NUL in headers
New parser rule: refuse HTTP requests where a header field value
contains characters that
a) should never appear there in the first place,
b) might have lead to incorrect treatment in a proxy in front, and
c) might lead to unintended behaviour in applications.

From RFC 9110 section 5.5:
"Field values containing CR, LF, or NUL characters are invalid and
dangerous, due to the varying ways that implementations might parse
and interpret those characters; a recipient of CR, LF, or NUL within
a field value MUST either reject the message or replace each of those
characters with SP before further processing or forwarding of that
message."
2024-07-31 01:28:30 +02:00
Paul J. Dorn
e710393d14 HTTP parser: stricter chunk-ext OBS handling
chunk extensions are silently ignored before and after this change;
its just the whitespace handling for the case without extensions that matters
applying same strip(WS)->rstrip(BWS) replacement as already done in related cases

half-way fix: could probably reject all BWS cases, rejecting only misplaced ones
2023-12-17 17:46:56 +01:00
Paul J. Dorn
7ebe442d08 strict HTTP version validation
Note: This is unrelated to a reverse proxy potentially talking HTTP/3 to clients.
This is about the HTTP protocol version spoken to Gunicorn, which is HTTP/1.0 or HTTP/1.1.

Little legitimate need for processing HTTP 1 requests with ambiguous version numbers.
Broadly refuse.

Co-authored-by: Ben Kallus <benjamin.p.kallus.gr@dartmouth.edu>
2023-12-15 13:33:31 +01:00
Paul J. Dorn
f5501111a2 strict HTTP header field name validation
Do the validation on the original, not the result from unicode case folding.

Background:
latin-1 0xDF is traditionally uppercased 0x53+0x53 which puts it back in ASCII
2023-12-15 13:33:31 +01:00
Paul J. Dorn
ac29c9b0a7 fail-safe on unsupported request framing
If we promise wsgi.input_terminated, we better get it right - or not at all.
* chunked encoding on HTTP <= 1.1
* chunked not last transfer coding
* multiple chinked codings
* any unknown codings (yes, this too! because we do not detect unusual syntax that is still chunked)
* empty coding (plausibly harmless, but not see in real life anyway - refused, for the moment)
2023-12-15 13:33:31 +01:00
Paul J. Dorn
72b8970dbf silently drop or refuse header names w/ underscore
Ambiguous mappings open a bottomless pit of "what is user input and what is proxy input" confusion.
Default to what everyone else has been doing for years now, silently drop.

see also https://nginx.org/r/underscores_in_headers
2023-12-15 13:33:31 +01:00
Paul J. Dorn
b2846783d7 strict: header field validation: stop casefolding
* refusing lowercase and ASCII 0x23 (#) had been partially enforced before
* do not casefold by default, HTTP methods are case sensitive
2023-12-15 13:33:31 +01:00
Ben Kallus
72238fcf8d RFC compliant request line and header parsing
- Unify HEADER_RE and METH_RE
- Replace CRLF with SP during obs-fold processing (See RFC 9112 Section 5.2, last paragraph)
- Stop stripping header names.
- Remove HTAB in OWS in header values that use obs-fold (See RFC 9112 Section 5.2, last paragraph)
- Use fullmatch instead of search, which has problems with empty strings. (See GHSA-68xg-gqqm-vgj8)
- Split proxy protocol line on space only. (See proxy protocol Section 2.1, bullet 3)
- Use fullmatch for method and version (Thank you to Paul Dorn for noticing this.)
- Replace calls to str.strip() with str.strip(' \t')
- Split request line on SP only.

Co-authored-by: Paul Dorn <pajod@users.noreply.github.com>
2023-12-15 13:33:31 +01:00
Jason Myers
fa94f70529 Updating Content-Length Handling
Signed-off-by: Jason Myers <jmyers@syntellis.com>
2023-05-30 20:42:13 -05:00
Emile Fugulin
ddf5e66ac8 Remove strict check of Transfer-Encoding 2019-11-20 12:25:39 -05:00
Emile Fugulin
f74324bd75 Handle multiple transfer-encoding 2019-11-18 22:29:02 -05:00
Emile Fugulin
bd8670b4db Handle duplicate content-length 2019-11-18 21:16:12 -05:00
Emile Fugulin
b798412444 Remove default strip of header name 2019-11-18 19:44:01 -05:00
Randall Leeds
b07532be75 Forbid contradictory secure scheme headers
When a request specifies contradictory secure scheme headers, raise a
parse error.
2018-01-10 12:10:35 -08:00
YuppY
5953148573 Do not strip leading slash from path (#1511)
Fixes #1512
2017-12-28 11:32:47 +03:00
Your Name
a912e305c9 Reject requests like "GET / HTTP/1a1"
Numbers must be separated by dot. This makes life
a little bit harder for attackers who would like to inject specially crafted packets after GET / (e.g. in nginx there are sometimes regular expressions like (?P<action>[^.]).html
2016-11-04 21:16:01 +03:00
Tobias Gustafsson
70cfb0d818 Remove upper limit on max header size config (#1313)
Fixes #1306
2016-09-17 12:49:05 +03:00
Randall Leeds
72c8be56fc Add test for #1023 2015-05-09 20:46:31 +03:00
Konstantin Kapustin
70534acde8 Implantation proxy protocol 2012-09-27 19:14:40 +02:00
Konstantin Kapustin
4be3282440 Check Content-Length header.
For not chunked request do validation Content-Length header and return 400 if invalid.
2012-09-27 19:14:40 +02:00
benoitc
d79ff999ce fix multiple issues with request limit
patch from Djoume Salvetti . address the following issues in gunicorn:

* Gunicorn does not limit the size of a request header (the
* limit_request_field_size configuration parameter is not used)

* When the configured request limit is lower than its maximum value, the
* maximum value is used instead. For instance if limit_request_line is
* set to 1024, gunicorn will only limit the request line to 4096 chars
* (this issue also affects limit_request_fields)

* Request limits are not limited to their maximum authorized values. For
* instance it is possible to set limit_request_line to 64K (this issue
* also affects limit_request_fields)

* Setting limit_request_fields and limit_request_field_size to 0 does
* not make them unlimited. The following patch allows limit_request_line
* and limit_request_field_size to be unlimited. limit_request_fields can
* no longer be unlimited (I can't imagine 32K fields to not be enough
* but I have a use case where 8K for the request line is not enough).

* Parsing errors (premature client disconnection) are not reported

* When request line limit is exceeded the configured value is reported
* instead of the effective value.
2012-05-24 12:13:34 +02:00
benoitc
7a1c58f236 test number of headers fields and size.
Add --limit-request-fields (limit_request_fields) and
--limit-request-field-size (limit-request-field-size) options.

- limit_request_fields:

    Value is a number from 0 (unlimited) to 32768. This parameter is
    used to limit the number of headers in a request to prevent DDOS
    attack. Used with the `limit_request_field_size` it allows more
    safety.

- limit_request_field_size:

    Value is a number from 0 (unlimited) to 8190. to set the limit
    on the allowed size of an HTTP request header field.
2012-02-20 10:36:13 +01:00
benoitc
b7b0979ad9 check if Request Line is too large.
You can now pass the parameter --limit-request-line or set the
limit_request_line in your configuration file to set the max size of the
request line in bytes.

This parameter is used to limit the allowed size of a client's HTTP
request-line. Since the request-line consists of the HTTP method, URI,
and protocol version, this directive places a restriction on the length
of a request-URI allowed for a request on the server. A server needs
this value to be large enough to hold any of its resource names,
including any information that might be passed in the query part of a
GET request. By default this value is 4094 and can't be larger than
8190.

This parameter can be used to prevent any DDOS attack.
2012-02-20 09:56:06 +01:00
Paul J. Davis
5af1273fc2 Added more valid request tests.
Found and fixed a couple read and readline related bugs.
2010-06-03 16:11:18 -04:00