From 592e4c736597f798a2d2740bf8f5a047766ff3e7 Mon Sep 17 00:00:00 2001 From: Yannick Alexander Date: Wed, 1 Apr 2026 11:13:18 +0200 Subject: [PATCH] updated regex to properly handle more cases, extended tests and update pattern access Signed-off-by: Yannick Alexander --- pkg/registry/client.go | 6 ++--- pkg/registry/client_test.go | 45 +++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/pkg/registry/client.go b/pkg/registry/client.go index 33ece53f1..cb89335a6 100644 --- a/pkg/registry/client.go +++ b/pkg/registry/client.go @@ -229,7 +229,7 @@ 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-z]*:\/\/)?(?P[a-zA-Z0-9-\.\:]+)(?P\/.*)?$`) +var hostRegex = regexp.MustCompile(`^(?P[a-zA-Z][a-zA-Z0-9+\-.]*:\/\/)?(?P[a-zA-Z0-9\-._:\[\]]+)(?P\/.*)?$`) // validateHost checks that the host matches some required pre-checks e.g. does not contain a scheme or path. // While ORAS will also validate some of these things, the current errors are a bit opaque. @@ -240,8 +240,8 @@ func validateHost(host string) error { return fmt.Errorf("invalid host: %q", host) } - scheme := matches[1] - path := matches[3] + scheme := matches[hostRegex.SubexpIndex("scheme")] + path := matches[hostRegex.SubexpIndex("path")] if scheme != "" { return fmt.Errorf("host should not contain a scheme (e.g. http://), found %q", scheme) diff --git a/pkg/registry/client_test.go b/pkg/registry/client_test.go index 5f91afa0d..0140b038c 100644 --- a/pkg/registry/client_test.go +++ b/pkg/registry/client_test.go @@ -169,6 +169,51 @@ func TestValidateHost(t *testing.T) { host: "oci://ghcr.io", wantErr: true, }, + { + name: "domain with uppercase scheme", + host: "HTTPS://ghcr.io", + wantErr: true, + }, + { + name: "scheme with plus sign", + host: "coap+tcp://ghcr.io", + wantErr: true, + }, + { + name: "scheme with dot and hyphen", + host: "my.custom-scheme://ghcr.io", + wantErr: true, + }, + { + name: "IPv6 loopback with port", + host: "[::1]:5000", + wantErr: false, + }, + { + name: "IPv6 full address with port", + host: "[2001:db8::1]:443", + wantErr: false, + }, + { + name: "IPv4 address with port", + host: "192.168.1.1:5000", + wantErr: false, + }, + { + name: "host with underscore", + host: "my_registry.local", + wantErr: false, + }, + { + name: "scheme with path", + host: "https://ghcr.io/myrepo", + wantErr: true, + }, + { + name: "empty string", + host: "", + wantErr: true, + }, } for _, tt := range tests {