Read the source host's port from the parsed URL (part of #246)
check / check (push) Waiting to run

net.SplitHostPort fails on an IPv6 address written without brackets,
so with 2001:db8::1 allowlisted, 2001:db8::1:8443 and 2001:db8::1:
counted as having no port and were served without a signature, though
the fetcher connects to port 8443. ValidateRequest now takes a host to
have a port when the parsed URL's Port() is set or the host ends in
":", as Go's URL parser and so the fetcher read it.

Model: opus-5-5
This commit is contained in:
2026-10-15 05:28:07 +00:00
parent 95cf7c9430
commit 74f62ddac9
+8 -6
View File
@@ -7,9 +7,9 @@ import (
"fmt"
"io"
"log/slog"
"net"
"net/url"
"runtime/debug"
"strings"
"time"
"github.com/dustin/go-humanize"
@@ -220,11 +220,13 @@ func (s *Service) ValidateRequest(req *ImageRequest) error {
}
// An allowlist entry names no port, so a host followed by ":", with or
// without a port, needs a signature. This is checked here and not in
// allowlist.IsAllowed, which also matches referer_blocklist, where a
// Referer must be blocked whatever its port.
_, _, splitErr := net.SplitHostPort(parsedURL.Host)
hostHasPort := splitErr == nil
// without a port, needs a signature. The port is read from the parsed
// URL, as the fetcher reads it: in an IPv6 address written without
// brackets, such as 2001:db8::1:8443, it is what follows the last ":".
// This is checked here and not in allowlist.IsAllowed, which also matches
// referer_blocklist, where a Referer must be blocked whatever its port.
hostHasPort := parsedURL.Port() != "" ||
strings.HasSuffix(parsedURL.Host, ":")
if !hostHasPort && s.allowlist.IsAllowed(parsedURL) {
return nil