diff --git a/core/src/main/java/org/springframework/security/util/matcher/InetAddressMatchers.java b/core/src/main/java/org/springframework/security/util/matcher/InetAddressMatchers.java index dbe4e7be654..69d43823ea9 100644 --- a/core/src/main/java/org/springframework/security/util/matcher/InetAddressMatchers.java +++ b/core/src/main/java/org/springframework/security/util/matcher/InetAddressMatchers.java @@ -48,6 +48,9 @@ public static Builder builder() { /** * Creates a new builder configured to match external (non-private) IP addresses. + *
+ * A {@code null} address and the wildcard addresses ({@code 0.0.0.0} and {@code ::}) + * are not treated as external. * @return a {@link Builder} configured to match external addresses */ public static Builder matchExternal() { @@ -314,6 +317,10 @@ public String toString() { * External addresses are any addresses that are not internal (private) addresses. * This matcher delegates to {@link InternalInetAddressMatcher} and negates the * result. + *
+ * A {@code null} address and the wildcard addresses ({@code 0.0.0.0} and {@code ::}) + * are not external. They do not identify a host that a request could originate from, + * so negating the internal check is not meaningful for them. * * @author Gábor Vaspöri * @author Kian Jamali @@ -335,6 +342,9 @@ private ExternalInetAddressMatcher() { @Override public boolean matches(@Nullable InetAddress address) { + if (address == null || address.isAnyLocalAddress()) { + return false; + } return !this.internalMatcher.matches(address); } diff --git a/core/src/test/java/org/springframework/security/util/matcher/InetAddressMatchersTests.java b/core/src/test/java/org/springframework/security/util/matcher/InetAddressMatchersTests.java index 387af3c3814..3232cd44c05 100644 --- a/core/src/test/java/org/springframework/security/util/matcher/InetAddressMatchersTests.java +++ b/core/src/test/java/org/springframework/security/util/matcher/InetAddressMatchersTests.java @@ -461,6 +461,19 @@ void matchesWhenIpv6UniqueLocalThenReturnsFalse(String address) throws Exception assertThat(matcher.matches(InetAddress.getByName(address))).isFalse(); } + @Test + void matchesWhenNullThenReturnsFalse() { + InetAddressMatcher matcher = InetAddressMatchers.matchExternal().build(); + assertThat(matcher.matches((InetAddress) null)).isFalse(); + } + + @ParameterizedTest + @ValueSource(strings = { "0.0.0.0", "::" }) + void matchesWhenWildcardThenReturnsFalse(String address) throws Exception { + InetAddressMatcher matcher = InetAddressMatchers.matchExternal().build(); + assertThat(matcher.matches(InetAddress.getByName(address))).isFalse(); + } + } @Nested