Fetch an IPv6 source host written without a port (closes #295) #296

Merged
clawbot merged 2 commits from issue-295-ipv6-host-without-port into next 2026-10-16 05:00:47 +02:00
Collaborator

Fixes #295.

validateURL in internal/httpfetcher cut a port off the source host with net.SplitHostPort. For an IPv6 address in brackets with no port, as in https://[2001:db8::a]/a.png, that call fails, so the brackets stayed on, the name lookup failed, and the request answered 500 through /v1/image/ and through an encrypted URL. The check now parses the source URL with net/url and takes the host from Hostname(), which drops the brackets whether or not a port follows. The address is then looked up, and a private one is refused with 403, as it already was with a port.

The fetcher's other uses of the host stay as they are: the dialer is always handed an address with a port, and the connection limit per host only uses the host text to tell hosts apart, which works with the brackets on.

The router test is the first commit, the fix the second. It sends both image routes an IPv6 source host with and without a port: a public address must be fetched, a private one refused with 403 without reaching the upstream.

Disclosure: the doc comment of TestGeneratorMakesOneImageURLForTwoSpellingsOfASourceURL still says the fetcher refuses an IPv6 address written without a port. It is left as it is, because an existing test may not change without approval.

Model: opus-5-5

Fixes https://git.eeqj.de/sneak/pixa/issues/295. `validateURL` in `internal/httpfetcher` cut a port off the source host with `net.SplitHostPort`. For an IPv6 address in brackets with no port, as in `https://[2001:db8::a]/a.png`, that call fails, so the brackets stayed on, the name lookup failed, and the request answered 500 through `/v1/image/` and through an encrypted URL. The check now parses the source URL with `net/url` and takes the host from `Hostname()`, which drops the brackets whether or not a port follows. The address is then looked up, and a private one is refused with 403, as it already was with a port. The fetcher's other uses of the host stay as they are: the dialer is always handed an address with a port, and the connection limit per host only uses the host text to tell hosts apart, which works with the brackets on. The router test is the first commit, the fix the second. It sends both image routes an IPv6 source host with and without a port: a public address must be fetched, a private one refused with 403 without reaching the upstream. Disclosure: the doc comment of `TestGeneratorMakesOneImageURLForTwoSpellingsOfASourceURL` still says the fetcher refuses an IPv6 address written without a port. It is left as it is, because an existing test may not change without approval. Model: opus-5-5
clawbot added the needs-review label 2026-10-16 04:25:45 +02:00
clawbot self-assigned this 2026-10-16 04:25:48 +02:00
Author
Collaborator

Review passed.

Model: opus-5-5

Review passed. Model: opus-5-5
clawbot added 2 commits 2026-10-16 04:54:37 +02:00
A router test against a test upstream that records each request: an
IPv6 source host written with and without a port, through a /v1/image/
URL with a signature and through an encrypted URL. A public address must
be fetched, a private one refused with 403 without reaching the
upstream. The cases without a port fail: each answers 500.

Model: opus-5-5
The fetcher's check of a source URL cut a port off the host with
net.SplitHostPort, which fails when an IPv6 address in brackets has no
port, so the brackets stayed on, the name lookup failed and the request
answered 500. The check now parses the URL and takes the host from
Hostname(), which drops the brackets with or without a port, so the
address is looked up and a private one is refused with 403.

Model: opus-5-5
clawbot force-pushed issue-295-ipv6-host-without-port from 3689685680 to 6f50eb20df 2026-10-16 04:54:37 +02:00 Compare
Author
Collaborator

Rebased onto next; no file conflicted, and only TODO.md needed its entry moved back to the top of Completed Steps.

Model: opus-5-5

Rebased onto `next`; no file conflicted, and only `TODO.md` needed its entry moved back to the top of Completed Steps. Model: opus-5-5
clawbot merged commit 08d6c3c459 into next 2026-10-16 05:00:47 +02:00
clawbot deleted branch issue-295-ipv6-host-without-port 2026-10-16 05:00:48 +02:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/pixa#296