diff --git a/src/Atc/Extensions/StringHasIsExtensions.cs b/src/Atc/Extensions/StringHasIsExtensions.cs
index ffb86e51..2987c795 100644
--- a/src/Atc/Extensions/StringHasIsExtensions.cs
+++ b/src/Atc/Extensions/StringHasIsExtensions.cs
@@ -598,11 +598,26 @@ public static bool IsUriOpcTcp(this string value)
/// Accepts single-label names (e.g. localhost) and an optional trailing dot (e.g. example.com.).
/// Each label is 1-63 ASCII alphanumeric/hyphen characters and may not start or end with a hyphen;
/// the total length is limited to 253 characters. Underscores and raw Unicode (non-punycode IDN) are not allowed.
+ /// Per RFC 1123 §2.1 the top-level (right-most) label must not be all-numeric, which also disambiguates
+ /// host names from IPv4 addresses (e.g. 192.168.0.27 is rejected).
/// This is a purely syntactic check and does not perform any DNS resolution.
///
public static bool IsHostName(this string value)
- => !string.IsNullOrEmpty(value) &&
- RxHostName.Value.IsMatch(value);
+ {
+ if (string.IsNullOrEmpty(value) ||
+ !RxHostName.Value.IsMatch(value))
+ {
+ return false;
+ }
+
+ var host = value.EndsWith('.')
+ ? value[..^1]
+ : value;
+
+ var topLevelLabel = host[(host.LastIndexOf('.') + 1)..];
+
+ return !topLevelLabel.All(char.IsDigit);
+ }
///
/// Determines whether the specified value is a valid IPv4 address.
diff --git a/test/Atc.Tests/Extensions/StringHasIsExtensionsTests.cs b/test/Atc.Tests/Extensions/StringHasIsExtensionsTests.cs
index 25b07587..0e29789c 100644
--- a/test/Atc.Tests/Extensions/StringHasIsExtensionsTests.cs
+++ b/test/Atc.Tests/Extensions/StringHasIsExtensionsTests.cs
@@ -384,6 +384,7 @@ public void IsUriOpcTcp(
[InlineData(true, "example.com.")]
[InlineData(true, "a.b.c.d.e.f")]
[InlineData(true, "xn--mnchen-3ya.de")]
+ [InlineData(true, "host123")]
[InlineData(false, "")]
[InlineData(false, " ")]
[InlineData(false, "-leadinghyphen.com")]
@@ -392,6 +393,10 @@ public void IsUriOpcTcp(
[InlineData(false, "double..dot.com")]
[InlineData(false, "space in.host")]
[InlineData(false, "münchen.de")]
+ [InlineData(false, "192.168.0.27")]
+ [InlineData(false, "1.2.3.4")]
+ [InlineData(false, "123")]
+ [InlineData(false, "example.123")]
public void IsHostName(
bool expected,
string input)