Opened 3 years ago

Closed 3 years ago

#32930 closed Bug (fixed)

URLValidator should accept urls with port number < 10

Reported by: Wu Haotian Owned by: Wu Haotian
Component: Core (Other) Version: 3.2
Severity: Normal Keywords: URLValidator
Cc: Collin Anderson, Florian Apolloner Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

>>> from django.core.validators import URLValidator
>>> URLValidator()("https://code.djangoproject.com:1")
Traceback (most recent call last):
    .....
    raise ValidationError(self.message, code=self.code, params={'value': value})
django.core.exceptions.ValidationError: <unprintable ValidationError object>

The commit[1] for fixing Ticket #20003 added port length checks in URLValidator, but I didn't see why in the ticket comments or commit description.

Given that:

The URL Standard from WhatWG[2] defines URL Port as:

A URL’s port is either null or a 16-bit unsigned integer that identifies a networking port. It is initially null.

RFC 3986[3] defines "port" as "*DIGIT", and does not requires the length of port.

I believe URLs with port number < 10 should be valid URLs.

[1] https://github.com/django/django/commit/2e65d56156b622e2393dee1af66e9c799a51924f#diff-d9609d8dc8482b30eac30df16213cba134562949fd62c97573927b89e880f85bR85
[2] https://url.spec.whatwg.org/#concept-url-port
[3] https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.3

Change History (9)

comment:1 by Wu Haotian, 3 years ago

Owner: changed from nobody to Wu Haotian
Status: newassigned
Summary: URLValidator does not accept urls with port number < 10URLValidator should accept urls with port number < 10

comment:2 by Nick Pope, 3 years ago

Triage Stage: UnreviewedAccepted

So I looked into why it was added in 2e65d56156b622e2393dee1af66e9c799a51924f but the best I could come up with is that is was copied from this gist. There are unaddressed comments, e.g. this one, about this issue with the port number and other things.

Note that this line is also affected and will need fixing.

We can change (?::\d{2,5})? to (?::\d{1,5})? to fix this naively.
Or we can be a little more strict as the port should only be a 16-bit unsigned integer (0-65535) and use the following to disallow 65536 and higher:

(?:[0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])?

comment:3 by Mariusz Felisiak, 3 years ago

Cc: Collin Anderson Florian Apolloner added

in reply to:  2 comment:4 by Florian Apolloner, 3 years ago

Replying to Nick Pope:

Or we can be a little more strict as the port should only be a 16-bit unsigned integer (0-65535) and use the following to disallow 65536 and higher:

(?:[0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])?

I would keep the regex simple and perform range validation on it afterwards… FWIW I do not think that 0 would be a valid port for a URL

comment:5 by Wu Haotian, 3 years ago

It's hard to validating port using regex only.. Given that 0443 and 000080 are both valid ports in URL.

>>> import requests
>>> requests.get("https://code.djangoproject.com:0443")
<Response [200]>
>>> requests.get("https://code.djangoproject.com:00000443")
<Response [200]>
> curl -I http://example.com:0000000000080
HTTP/1.1 200 OK
Content-Encoding: gzip
Accept-Ranges: bytes
Age: 591287
Cache-Control: max-age=604800
Content-Type: text/html; charset=UTF-8
Date: Thu, 15 Jul 2021 09:51:52 GMT
Etag: "3147526947"
Expires: Thu, 22 Jul 2021 09:51:52 GMT
Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
Server: ECS (sab/5693)
X-Cache: HIT
Content-Length: 648

I'd prefer to use \d+ -- it's not perfect, but should produce fewer false negatives.

comment:6 by Jacob Walls, 3 years ago

Has patch: set

comment:7 by Mariusz Felisiak, 3 years ago

Patch needs improvement: set

comment:8 by Mariusz Felisiak, 3 years ago

Patch needs improvement: unset
Triage Stage: AcceptedReady for checkin

comment:9 by Mariusz Felisiak <felisiak.mariusz@…>, 3 years ago

Resolution: fixed
Status: assignedclosed

In 65b880b:

Fixed #32930 -- Fixed URLValidator when port numbers < 10.

Note: See TracTickets for help on using tickets.
Back to Top