You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In Rack 2.1.2, Rack::Request#host did no hostname validation, returning everything from #host_with_port up to the colon.
defhost# Remove port number.h=host_with_portifcolon_index=h.index(":")h[0,colon_index]elsehendend
This did not support IPv6 well, so #1561 was implemented to solve that. This changed the implementation of #host to one that relied on regular expressions. This was released in Rack 2.2.0.
defhostsplit_authority(self.authority)[0]enddefauthorityforwarded_authority || host_authority || server_authorityenddefforwarded_authorityifvalue=get_header(HTTP_X_FORWARDED_HOST)wrap_ipv6(split_header(value).first)endenddefhost_authorityget_header(HTTP_HOST)enddefserver_authorityhost=self.server_nameport=self.server_portifhostifport"#{host}:#{port}"elsehostendendenddefsplit_authority(authority)ifmatch=AUTHORITY.match(authority)ifaddress=match[:ip6]returnmatch[:host],address,match[:port]&.to_ielsereturnmatch[:host],match[:host],match[:port]&.to_iendend# Give up!returnauthority,authority,nilendAUTHORITY=/ # The host: (?<host> # An IPv6 address: (\[(?<ip6>.*)\]) | # An IPv4 address: (?<ip4>[\d\.]+) | # A hostname: (?<name>[a-zA-Z0-9\.\-]+) ) # The optional port: (:(?<port>\d+))? /x
This provided not only better IPv6 support, but also did some validation of hostnames, as per RFC 952.
It was soon discovered that this was improperly parsing hostnames that were valid under the more lenient RFC 1123 (permitting hostnames to begin with digits and hyphens) as IP addresses (#1590), so in #1591, the regular expression was updated to match [an entire line of] the authority. This was released as Rack 2.2.2.
AUTHORITY=/^ # The host: (?<host> # An IPv6 address: (\[(?<ip6>.*)\]) | # An IPv4 address: (?<ip4>[\d\.]+) | # A hostname: (?<name>[a-zA-Z0-9\.\-]+) ) # The optional port: (:(?<port>\d+))? $/x
The Issue
While the match being performed in the AUTHORITY regex is technically correct for hostnames, it is not correct for DNS names (as per RFC 2181, Section 11). This also causes issues in environments like Docker, where some tools (e.g. Docker Compose) implicitly create hostnames containing underscores. These hostnames are being truncated in Rack 2.2.0, and being left unprocessed in Rack 2.2.2.
Suggestions
Given RFC 2181 relaxes all restrictions on DNS names (except segment and total length), it seems unnecessarily risky to use anything but a wildcard match in that position. IP addresses, however, have a very predictable form, and regular expressions for matching them correctly are already a part of the Ruby standard library (see Resolv::IPv4::Regex and Resolv::IPv6::Regex) in every supported version of Ruby.
The text was updated successfully, but these errors were encountered:
On Sat, Feb 15, 2020 at 2:44 AM Samuel Williams ***@***.***> wrote:
Thanks for the detailed explanation. I agree everything you say.
I need a little bit more time to review, but I'm open making this
behaviour less specific. Do you want to make a PR to start with?
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#1604?email_source=notifications&email_token=AAAASLSGEY2DQ2376C3JVCDRC7BQZA5CNFSM4KVWLIN2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEL3HLWI#issuecomment-586577369>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAASLTMYWFAQUGG7FNIW4TRC7BQZANCNFSM4KVWLINQ>
.
In Rack 2.1.2,
Rack::Request#host
did no hostname validation, returning everything from#host_with_port
up to the colon.This did not support IPv6 well, so #1561 was implemented to solve that. This changed the implementation of
#host
to one that relied on regular expressions. This was released in Rack 2.2.0.This provided not only better IPv6 support, but also did some validation of hostnames, as per RFC 952.
It was soon discovered that this was improperly parsing hostnames that were valid under the more lenient RFC 1123 (permitting hostnames to begin with digits and hyphens) as IP addresses (#1590), so in #1591, the regular expression was updated to match [an entire line of] the authority. This was released as Rack 2.2.2.
The Issue
While the match being performed in the
AUTHORITY
regex is technically correct for hostnames, it is not correct for DNS names (as per RFC 2181, Section 11). This also causes issues in environments like Docker, where some tools (e.g. Docker Compose) implicitly create hostnames containing underscores. These hostnames are being truncated in Rack 2.2.0, and being left unprocessed in Rack 2.2.2.Suggestions
Given RFC 2181 relaxes all restrictions on DNS names (except segment and total length), it seems unnecessarily risky to use anything but a wildcard match in that position. IP addresses, however, have a very predictable form, and regular expressions for matching them correctly are already a part of the Ruby standard library (see
Resolv::IPv4::Regex
andResolv::IPv6::Regex
) in every supported version of Ruby.The text was updated successfully, but these errors were encountered: