Lower-case the image URL's host and require a signature for a port (closes #246)
check / check (push) Waiting to run
check / check (push) Waiting to run
With cdn.example.com allowlisted, CDN.Example.com and cdn.example.com:8443 passed the allowlist too, and each spelling had its own cache entries and its own connections under upstream_connections_per_host. The image URL parser now lower-cases the host and refuses one holding "@" with ErrInvalidHost (400). ValidateRequest counts a host followed by ":", with or without a port, as not allowlisted, so it needs a signature. That check is not in allowlist.IsAllowed, which also matches referer_blocklist. A URL is now signed over the lower-cased host; README.md says so. Model: opus-5-5
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net"
|
||||
"net/url"
|
||||
"runtime/debug"
|
||||
"time"
|
||||
@@ -218,7 +219,14 @@ func (s *Service) ValidateRequest(req *ImageRequest) error {
|
||||
return fmt.Errorf("invalid source URL: %w", err)
|
||||
}
|
||||
|
||||
if s.allowlist.IsAllowed(parsedURL) {
|
||||
// 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
|
||||
|
||||
if !hostHasPort && s.allowlist.IsAllowed(parsedURL) {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -144,6 +144,16 @@ func parseImageComponents(remainder string) (*ParsedURL, error) {
|
||||
return nil, ErrMissingHost
|
||||
}
|
||||
|
||||
// A URL reads what comes before "@" as a user name and password, and the
|
||||
// rest as the host
|
||||
if strings.Contains(host, "@") {
|
||||
return nil, fmt.Errorf("%w: %q holds @", ErrInvalidHost, host)
|
||||
}
|
||||
|
||||
// Host names do not depend on letter case, so the allowlist, the upstream
|
||||
// connection limits and the cache see one spelling of each host
|
||||
host = strings.ToLower(host)
|
||||
|
||||
// Extract query string if present in path
|
||||
if qIndex := strings.Index(path, "?"); qIndex != -1 {
|
||||
query = path[qIndex+1:]
|
||||
|
||||
Reference in New Issue
Block a user