Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion baked_in.go
Original file line number Diff line number Diff line change
Expand Up @@ -2798,8 +2798,33 @@ func isHostnameRFC952(fl FieldLevel) bool {
return hostnameRegexRFC952().MatchString(fl.Field().String())
}

// looksLikeDottedDecimal returns true if s looks like a dotted-decimal address
// (e.g. "277.168.0.1") — composed entirely of digits and dots, with at least one dot.
func looksLikeDottedDecimal(s string) bool {
hasDot := false
for _, c := range s {
if c == '.' {
hasDot = true
} else if c < '0' || c > '9' {
return false
}
}
return hasDot

Copilot AI Apr 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looksLikeDottedDecimal returns true for any string containing only digits and dots with at least one dot (e.g. "1.2" or "1.2.3"). That means isHostnameRFC1123 will now reject these values even though hostnameRegexRFC1123 allows them, and the RFC 1123 quote/comment here specifically refers to the IPv4-like form #.#.#.#. Consider tightening the check to only treat the input as “dotted-decimal” when it has exactly 4 numeric labels (3 dots, no empty labels), so you only gate IPv4-shaped inputs behind net.ParseIP.

Suggested change
// looksLikeDottedDecimal returns true if s looks like a dotted-decimal address
// (e.g. "277.168.0.1") — composed entirely of digits and dots, with at least one dot.
func looksLikeDottedDecimal(s string) bool {
hasDot := false
for _, c := range s {
if c == '.' {
hasDot = true
} else if c < '0' || c > '9' {
return false
}
}
return hasDot
// looksLikeDottedDecimal returns true if s looks like a dotted-decimal IPv4
// address shape (e.g. "277.168.0.1"): exactly 4 numeric labels separated by
// 3 dots, with no empty labels.
func looksLikeDottedDecimal(s string) bool {
parts := strings.Split(s, ".")
if len(parts) != 4 {
return false
}
for _, part := range parts {
if part == "" {
return false
}
for _, c := range part {
if c < '0' || c > '9' {
return false
}
}
}
return true

Copilot uses AI. Check for mistakes.
}

func isHostnameRFC1123(fl FieldLevel) bool {
return hostnameRegexRFC1123().MatchString(fl.Field().String())
val := fl.Field().String()
if !hostnameRegexRFC1123().MatchString(val) {
return false
}
// RFC 1123 §2.1: "a valid host name can never have the dotted-decimal
// form #.#.#.#, since at least the highest-level component label will
// be alphabetic." Reject strings that look like dotted-decimal but are
// not valid IPv4 addresses (e.g. 277.168.0.1).
if net.ParseIP(val) == nil && looksLikeDottedDecimal(val) {

Copilot AI Apr 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In isHostnameRFC1123, net.ParseIP(val) is evaluated for every value that matches the hostname regex, including typical hostnames like "example.com". To avoid unnecessary parsing work, check looksLikeDottedDecimal(val) first and only call net.ParseIP when the string is actually numeric/dotted.

Suggested change
if net.ParseIP(val) == nil && looksLikeDottedDecimal(val) {
if looksLikeDottedDecimal(val) && net.ParseIP(val) == nil {

Copilot uses AI. Check for mistakes.
return false
}
return true
}

func isFQDN(fl FieldLevel) bool {
Expand Down