From 3e6189a231f50944c43e35345384f4d1ce17cffb Mon Sep 17 00:00:00 2001 From: Sasha Mitchell Date: Wed, 30 Sep 2026 20:49:07 +0700 Subject: [PATCH] fix: reject a bracketed host that is not an IPv6 address Parse("[:::]:5000/repo") returned a reference. The name regexp accepts any hex and colons inside the brackets, and "[:::]" is not an IPv6 address. Signed-off-by: Sasha Mitchell --- reference.go | 22 ++++++++++++++++++++++ reference_test.go | 12 ++++++++++++ 2 files changed, 34 insertions(+) diff --git a/reference.go b/reference.go index c343cf6..d6560c9 100644 --- a/reference.go +++ b/reference.go @@ -52,6 +52,7 @@ package reference import ( "errors" "fmt" + "net" "strings" "github.com/opencontainers/go-digest" @@ -203,6 +204,21 @@ func Path(named Named) (name string) { return path } +// validateIPv6Host rejects a bracketed host that is not an IP address. +// The reference grammar uses an RFC 3986 IPv6address. The name regexp only +// checks that the brackets contain hex digits and colons, so "[:::]" and +// "[fd00123123123]" used to parse. +func validateIPv6Host(domain string) error { + if domain == "" || domain[0] != '[' { + return nil + } + end := strings.IndexByte(domain, ']') + if end <= 1 || net.ParseIP(domain[1:end]) == nil { + return ErrReferenceInvalidFormat + } + return nil +} + // splitDomain splits a named reference into a hostname and path string. // If no valid hostname is found, the hostname is empty and the full value // is returned as name @@ -255,6 +271,9 @@ func Parse(s string) (Reference, error) { if len(repo.path) > RepositoryNameTotalLengthMax { return nil, ErrNameTooLong } + if err := validateIPv6Host(repo.domain); err != nil { + return nil, err + } ref := reference{ namedRepository: repo, @@ -302,6 +321,9 @@ func WithName(name string) (Named, error) { if len(match[2]) > RepositoryNameTotalLengthMax { return nil, ErrNameTooLong } + if err := validateIPv6Host(match[1]); err != nil { + return nil, err + } return repository{ domain: match[1], diff --git a/reference_test.go b/reference_test.go index ac46e93..effa231 100644 --- a/reference_test.go +++ b/reference_test.go @@ -271,6 +271,18 @@ func TestReferenceParse(t *testing.T) { input: "[fe80::1%@invalidzone]:5000/repo", err: ErrReferenceInvalidFormat, }, + { + input: "[:::]:5000/repo", + err: ErrReferenceInvalidFormat, + }, + { + input: "[:::::::]:5000/repo", + err: ErrReferenceInvalidFormat, + }, + { + input: "[fd00123123123]:75050/repo", + err: ErrReferenceInvalidFormat, + }, { input: "example.com/" + strings.Repeat("a", 255) + ":tag", domain: "example.com",