diff --git a/pkg/registry/client.go b/pkg/registry/client.go index cb89335a6..4a740eed1 100644 --- a/pkg/registry/client.go +++ b/pkg/registry/client.go @@ -227,28 +227,36 @@ type ( } ) -// hostRegex is a pretty naive regex for validating host urls. The goal of it is not to ultimately validate all possible valid hosts, -// but to catch common user errors such as including a scheme or path in the host string. -var hostRegex = regexp.MustCompile(`^(?P[a-zA-Z][a-zA-Z0-9+\-.]*:\/\/)?(?P[a-zA-Z0-9\-._:\[\]]+)(?P\/.*)?$`) +// schemeRegex is used to check if a schema is present within the host - we have to do so, to determine if we need +// to prepend a "dummy://" schema for url.Parse to not accidentally interpret the host as just a path +var schemeRegex = regexp.MustCompile(`^(?P[a-zA-Z][a-zA-Z0-9+\-.]*:\/\/).*$`) -// validateHost checks that the host matches some required pre-checks e.g. does not contain a scheme or path. +// validateHost checks that the host matches some required pre-checks e.g. does not contain a scheme, query or path. // While ORAS will also validate some of these things, the current errors are a bit opaque. // By validating these things upfront, we can provide clearer error messages to users when they attempt to login with an invalid host string. func validateHost(host string) error { - matches := hostRegex.FindStringSubmatch(host) + if strings.TrimSpace(host) == "" { + return fmt.Errorf("host cannot be empty") + } + + matches := schemeRegex.FindStringSubmatch(host) if len(matches) == 0 { - return fmt.Errorf("invalid host: %q", host) + host = "dummy://" + host } - scheme := matches[hostRegex.SubexpIndex("scheme")] - path := matches[hostRegex.SubexpIndex("path")] + url, err := url.Parse(host) + if err != nil { + return fmt.Errorf("invalid host %q: %w", host, err) + } - if scheme != "" { - return fmt.Errorf("host should not contain a scheme (e.g. http://), found %q", scheme) + // we check that no schema and query is present + if url.Scheme != "dummy" || url.RawQuery != "" { + return fmt.Errorf("host should not contain a scheme, query or fragement") } - if path != "" { - return fmt.Errorf("host should not contain a path, found %q", path) + // currently, paths are also not supported + if url.Path != "" && url.Path != "/" { + return fmt.Errorf("host should not contain a path, found %q", url.Path) } return nil