Refuse an image URL whose host is not a host name or IP address (closes #275)
check / check (push) Canceled after 0s

A ? written into the host segment as %3F reached the parser decoded,
so cdn.example.com?x=1 passed the allowlist as cdn.example.com, fetched
the host's root path with that query, and was cached under its own keys:
another unsigned spelling of one upstream request. The host segment is
now accepted only as a host name, an IPv4 address or a bracketed IPv6
address, with an optional port, and anything else is refused with 400.
An IPv6 address without brackets is now refused instead of needing a
signature; a host name outside ASCII is refused, its punycode accepted.

Model: opus-5-5
This commit was merged in pull request #285.
This commit is contained in:
2026-10-16 01:14:51 +02:00
parent 22bfc432b6
commit 62b4f4791e
4 changed files with 115 additions and 5 deletions
+11
View File
@@ -30,6 +30,17 @@ P2: security: per-origin rate limiting
# Completed Steps
- 2026-10-15 the host of a `/v1/image/` URL must be a host name or an IPv4
address (letters, digits, hyphens, underscores and dots) or an IPv6 address in
brackets, either one optionally followed by `:` and a port, and any other host
is refused with 400 (closes #275): only `@` was refused, so a `?` written as
`%3F` gave the host `cdn.example.com?x=1`, which Go's URL parser reads as
`cdn.example.com` with a query. Such a URL passed the allowlist, and each text
after the `?` fetched the host's root path and cached the answer under keys of
its own. A `#`, `%`, `\` or space written percent-encoded is refused the same
way, and so is an IPv6 address without brackets, which needed a signature
before. Underscores are kept because `allowlist_hosts` accepts host names
holding them.
- 2026-10-15 the README says how a source URL with a query is written into an
image URL, and the image route accepts it (closes #255): the query follows the
source path after `%3F`. pixa now reads the image URL's path decoded once, so