Fix HTTP01.uri for IPv6 addresses (#10548)

IPv6 addresses in URLs should be enclosed in square brackets.

Note: I chose to fix this by parsing the identifier rather than changing
the method signature. The obvious choice to change the method signature
would be to take `messages.Identifier`. We could even do this backwards
compatibly by taking `str | messages.Identifier`. However, `messages`
imports `challenges`, so referencing `messages.Identifier` here would
require an import loop.

I also considered implementing a new method on, e.g.
messages.Authorization that would take a challenge as a parameter. But
this would be suboptimal because the `uri` method really is specific to
the http-01 challenge type, so it's nice to have it implemented only on
the relevant class.
This commit is contained in:
Jacob Hoffman-Andrews 2026-01-27 20:42:52 -08:00 committed by GitHub
parent 3b9a1d0d64
commit bd7b64f1e7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 18 additions and 3 deletions

View file

@ -244,6 +244,12 @@ class HTTP01Test(unittest.TestCase):
assert 'http://example.com/.well-known/acme-challenge/' \
'evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA' == \
self.msg.uri('example.com')
assert 'http://1.2.3.4/.well-known/acme-challenge/' \
'evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA' == \
self.msg.uri('1.2.3.4')
assert 'http://[::1]/.well-known/acme-challenge/' \
'evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA' == \
self.msg.uri('::1')
def test_to_partial_json(self):
assert self.jmsg == self.msg.to_partial_json()

View file

@ -2,6 +2,7 @@
import abc
import functools
import hashlib
import ipaddress
import logging
from typing import Any
from typing import cast
@ -365,17 +366,24 @@ class HTTP01(KeyAuthorizationChallenge):
"""
return '/' + self.URI_ROOT_PATH + '/' + self.encode('token')
def uri(self, domain: str) -> str:
def uri(self, identifier: str) -> str:
"""Create an URI to the provisioned resource.
Forms an URI to the HTTPS server provisioned resource
(containing :attr:`~SimpleHTTP.token`).
:param str domain: Domain name being verified.
:param str identifier: Domain name or IP address being verified.
:rtype: str
"""
return "http://" + domain + self.path
try:
# https://datatracker.ietf.org/doc/html/rfc2732#section-2
# IPv6 addresses in URLs should be enclosed in brackets.
ipaddress.IPv6Address(identifier)
identifier = "[" + identifier + "]"
except ipaddress.AddressValueError:
pass
return "http://" + identifier + self.path
def validation(self, account_key: jose.JWK, **unused_kwargs: Any) -> str:
"""Generate validation.

View file

@ -0,0 +1 @@
The HTTP01.uri method will now properly enclose IPv6 addresses in square brackets.