Fetch an IPv6 source host written without a port (closes #295)
check / check (push) Waiting to run

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
This commit is contained in:
2026-10-16 02:49:55 +00:00
committed by clawbot
parent 1aacf6cbf6
commit 6f50eb20df
2 changed files with 14 additions and 8 deletions
+6
View File
@@ -30,6 +30,12 @@ P2: security: per-origin rate limiting
# Completed Steps # Completed Steps
- 2026-10-16 a source host that is an IPv6 address in brackets with no port,
such as `[2001:db8::a]`, is fetched like one with a port, through `/v1/image/`
and through an encrypted URL (closes #295). The fetcher's check of the source
URL kept the brackets when no port followed them, could not look the host up,
and the request answered 500. It now checks the address without brackets, so a
private one is refused with 403, as with a port.
- 2026-10-16 a `state_dir` whose name holds `%`, `?` or `#` keeps its database - 2026-10-16 a `state_dir` whose name holds `%`, `?` or `#` keeps its database
at `state.sqlite3` in that directory (closes #290): the `db_url` derived from at `state.sqlite3` in that directory (closes #290): the `db_url` derived from
it put the name into a `file:` URL as it was, so SQLite read `%41` as `A`, a it put the name into a `file:` URL as it was, so SQLite read `%41` as `A`, a
+8 -8
View File
@@ -473,16 +473,16 @@ func validateURL(ctx context.Context, rawURL string, allowHTTP bool) error {
return ErrUnsupportedScheme return ErrUnsupportedScheme
} }
// Parse to extract host parsedURL, err := neturl.Parse(rawURL)
host := extractHost(rawURL) if err != nil {
if host == "" { return fmt.Errorf("%w: %w", ErrInvalidHost, err)
return ErrInvalidHost
} }
// Remove port if present // Hostname drops any port, and the brackets of an IPv6 address whether
h, _, err := net.SplitHostPort(host) // or not a port follows them
if err == nil { host := parsedURL.Hostname()
host = h if host == "" {
return ErrInvalidHost
} }
// Block obvious localhost patterns // Block obvious localhost patterns