Skip to content

reqs: end the host at '?' and '#', not only at '/' - #645

Open
Allsimon wants to merge 1 commit into
tinyproxy:masterfrom
Allsimon:host-ends-at-query
Open

Allsimon wants to merge 1 commit into
tinyproxy:masterfrom
Allsimon:host-ends-at-query

Conversation

@Allsimon

Copy link
Copy Markdown

extract_url() splits the host from the path on the first / only. A request-target like http://example.com?q=1 is valid absolute-form (RFC 3986 §3.2: the authority ends at /, ? or #), but tinyproxy keeps the query in the host: it tries to resolve example.com?q=1, and Filter matches against that string instead of the host.

I hit this with a Java application whose HTTP client sends GET http://search.example.net?type=artist&query=... HTTP/1.1 with no / before the query. With FilterDefaultDeny Yes every one of those requests was refused, although the domain was allowed.

This splits on the first of /, ? or #, and gives a path that starts with ? or # its leading /.

Raw request lines (curl normalises the URL, so these were sent over a plain socket), with a filter allowing only (^|\.)example\.com$:

request-target before after
http://example.com?q=1 403 Filtered 200
http://example.com#frag 403 Filtered 200
http://[email protected]?q=1 403 Filtered 200
http://evil.invalid?.example.com passes the filter, 500 Unable to connect 403 Filtered
http://evil.invalid#.example.com passes the filter, 500 Unable to connect 403 Filtered
http://example.com:80?q=1 200 200
http://example.com/?q=1 200 200

Built and tested on master; no new compiler warnings.

extract_url() split the host from the path on the first '/', so a
request-target like "http://example.com?q=1", which is valid absolute-form
(RFC 3986 section 3.2: the authority ends at '/', '?' or '#'), left the
query in the host: tinyproxy tried to resolve "example.com?q=1", and the
filter matched against that string instead of the host.

Split on the first of '/', '?' or '#', and give a path that starts with
'?' or '#' its leading '/'.
@rofl0r

rofl0r commented Oct 25, 2026

Copy link
Copy Markdown
Contributor

please quote the relevant section of the RFC allowing this. the only thing i found is

The path is terminated
by the first question mark ("?") or number sign ("#") character, or
by the end of the URI.

refering to path, not host.

@Allsimon

Copy link
Copy Markdown
Author

The authority component is preceded by a double slash ("//") and is
terminated by the next slash ("/"), question mark ("?"), or number
sign ("#") character, or by the end of the URI.

I think at this point in the code we are working with the authority instead of just the host (it strips the username_password then the port a few lines later

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.

2 participants