Skip to content

fix: reject requests with malformed request-line#100

Open
kugland wants to merge 2 commits into
emikulic:masterfrom
kugland:fix/reject-space-in-request-target
Open

fix: reject requests with malformed request-line#100
kugland wants to merge 2 commits into
emikulic:masterfrom
kugland:fix/reject-space-in-request-target

Conversation

@kugland
Copy link
Copy Markdown
Contributor

@kugland kugland commented May 16, 2026

Fixes #99.

parse_request() stopped URL parsing at the first space, then treated the next token as the HTTP version. This allowed a literal space in the request-target to go undetected — the server would silently truncate the URL and continue. Additionally, extra tokens after the HTTP version (e.g. GET / HTTP/1.1 HTTP/1.1) were silently ignored.

Changes

darkhttpd.c

  • Accept only HTTP/1.0 or HTTP/1.1 as valid version tokens (previously accepted any HTTP/ prefix). An unrecognised token means the URL contained a literal space → 400.
  • Reject the request if a non-whitespace character follows the version on the same line (extra tokens).
  • Stop the version-token loop at \n so bare-LF requests are handled symmetrically with CRLF.
  • Force conn_close = 1 in process_request() when parse_request() fails, so the 400 reply always closes the connection (previously, if HTTP/1.1 had been parsed before the failure, the connection was incorrectly kept alive).

devel/test.py

  • Table entry for GET /foo bar HTTP/1.1 → 400.
  • TestMalformedRequestLine.test_extra_token_after_version: sends GET / HTTP/1.1 HTTP/1.1 via raw socket → 400.

kugland added 2 commits May 15, 2026 22:22
Add test cases for two forms of invalid request-line:
- a literal space in the request-target (e.g. GET /foo bar HTTP/1.1),
  which is invalid per RFC 9112 and should return 400 Bad Request;
- extra tokens after the HTTP version (e.g. GET / HTTP/1.1 HTTP/1.1),
  which should likewise be rejected.
In parse_request(), after parsing the HTTP version token, reject the
request if:
- the token is not HTTP/1.0 or HTTP/1.1 (catches literal spaces in
  the request-target, which cause the URL parser to stop early and
  treat the next word as the version);
- a non-whitespace character follows the version on the same line
  (catches extra tokens such as GET / HTTP/1.1 HTTP/1.1).

Also stop the version-token loop at '\n' so bare-LF requests are
handled correctly, and force conn_close=1 in process_request() when
parse_request() fails so the 400 reply always closes the connection.
@kugland kugland force-pushed the fix/reject-space-in-request-target branch from 0ea96d1 to 99a9c25 Compare May 16, 2026 01:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Requests with a literal space in the request-target are accepted instead of rejected

1 participant