From e27c72eeb9e6e368eabd8e0bf6316c41b71faf32 Mon Sep 17 00:00:00 2001 From: Lee JiWon Date: Tue, 7 Apr 2026 22:00:34 +0900 Subject: [PATCH 1/2] Handle invalid regex pattern in EnvironmentEndpoint See gh-49942 Signed-off-by: Lee JiWon --- .../boot/actuate/env/EnvironmentEndpoint.java | 14 +++++++++++++- .../boot/actuate/env/EnvironmentEndpointTests.java | 10 ++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/env/EnvironmentEndpoint.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/env/EnvironmentEndpoint.java index fe17f7a8477..4d55a9ff3a6 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/env/EnvironmentEndpoint.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/env/EnvironmentEndpoint.java @@ -23,10 +23,12 @@ import java.util.List; import java.util.Map; import java.util.function.Predicate; import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; import java.util.stream.Stream; import com.fasterxml.jackson.annotation.JsonInclude; +import org.springframework.boot.actuate.endpoint.InvalidEndpointRequestException; import org.springframework.boot.actuate.endpoint.OperationResponseBody; import org.springframework.boot.actuate.endpoint.SanitizableData; import org.springframework.boot.actuate.endpoint.Sanitizer; @@ -87,11 +89,21 @@ public class EnvironmentEndpoint { EnvironmentDescriptor getEnvironmentDescriptor(String pattern, boolean showUnsanitized) { if (StringUtils.hasText(pattern)) { - return getEnvironmentDescriptor(Pattern.compile(pattern).asPredicate(), showUnsanitized); + return getEnvironmentDescriptor(getPatternPredicate(pattern), showUnsanitized); } return getEnvironmentDescriptor((name) -> true, showUnsanitized); } + private Predicate getPatternPredicate(String pattern) { + try { + return Pattern.compile(pattern).asPredicate(); + } + catch (PatternSyntaxException ex) { + throw new InvalidEndpointRequestException("Pattern '" + pattern + "' is not a valid regular expression", + ex.getMessage()); + } + } + private EnvironmentDescriptor getEnvironmentDescriptor(Predicate propertyNamePredicate, boolean showUnsanitized) { List propertySources = new ArrayList<>(); diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/env/EnvironmentEndpointTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/env/EnvironmentEndpointTests.java index 484a58d101a..34af01ba286 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/env/EnvironmentEndpointTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/env/EnvironmentEndpointTests.java @@ -27,6 +27,7 @@ import java.util.Map; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; +import org.springframework.boot.actuate.endpoint.InvalidEndpointRequestException; import org.springframework.boot.actuate.endpoint.Show; import org.springframework.boot.actuate.env.EnvironmentEndpoint.EnvironmentDescriptor; import org.springframework.boot.actuate.env.EnvironmentEndpoint.EnvironmentEntryDescriptor; @@ -48,6 +49,7 @@ import org.springframework.core.io.InputStreamSource; import org.springframework.mock.env.MockPropertySource; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; /** * Tests for {@link EnvironmentEndpoint}. @@ -69,6 +71,14 @@ class EnvironmentEndpointTests { System.clearProperty("VCAP_SERVICES"); } + @Test + void invalidPatternThrowsInvalidEndpointRequestException() { + ConfigurableEnvironment environment = emptyEnvironment(); + EnvironmentEndpoint endpoint = new EnvironmentEndpoint(environment, Collections.emptyList(), Show.ALWAYS); + assertThatExceptionOfType(InvalidEndpointRequestException.class).isThrownBy(() -> endpoint.environment("[")) + .withMessageContaining("Pattern '[' is not a valid regular expression"); + } + @Test void basicResponse() { ConfigurableEnvironment environment = emptyEnvironment(); From 2181ce095c70366827d44d9d9f6c36a83730c374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Nicoll?= Date: Tue, 7 Apr 2026 17:28:34 +0200 Subject: [PATCH 2/2] Polish "Handle invalid regex pattern in EnvironmentEndpoint" See gh-49942 --- .../boot/actuate/env/EnvironmentEndpoint.java | 10 +++++----- .../actuate/env/EnvironmentEndpointTests.java | 18 ++++++++++-------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/env/EnvironmentEndpoint.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/env/EnvironmentEndpoint.java index 4d55a9ff3a6..dcdfa70aa0a 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/env/EnvironmentEndpoint.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/env/EnvironmentEndpoint.java @@ -89,18 +89,18 @@ public class EnvironmentEndpoint { EnvironmentDescriptor getEnvironmentDescriptor(String pattern, boolean showUnsanitized) { if (StringUtils.hasText(pattern)) { - return getEnvironmentDescriptor(getPatternPredicate(pattern), showUnsanitized); + return getEnvironmentDescriptor(parsePattern(pattern).asPredicate(), showUnsanitized); } return getEnvironmentDescriptor((name) -> true, showUnsanitized); } - private Predicate getPatternPredicate(String pattern) { + private Pattern parsePattern(String pattern) { try { - return Pattern.compile(pattern).asPredicate(); + return Pattern.compile(pattern); } catch (PatternSyntaxException ex) { - throw new InvalidEndpointRequestException("Pattern '" + pattern + "' is not a valid regular expression", - ex.getMessage()); + throw new InvalidEndpointRequestException("Failed to parse regular expression: " + pattern, + "Invalid regular expression", ex); } } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/env/EnvironmentEndpointTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/env/EnvironmentEndpointTests.java index 34af01ba286..f3fa3ca0c3c 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/env/EnvironmentEndpointTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/env/EnvironmentEndpointTests.java @@ -23,6 +23,7 @@ import java.math.BigInteger; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; +import java.util.regex.PatternSyntaxException; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; @@ -71,14 +72,6 @@ class EnvironmentEndpointTests { System.clearProperty("VCAP_SERVICES"); } - @Test - void invalidPatternThrowsInvalidEndpointRequestException() { - ConfigurableEnvironment environment = emptyEnvironment(); - EnvironmentEndpoint endpoint = new EnvironmentEndpoint(environment, Collections.emptyList(), Show.ALWAYS); - assertThatExceptionOfType(InvalidEndpointRequestException.class).isThrownBy(() -> endpoint.environment("[")) - .withMessageContaining("Pattern '[' is not a valid regular expression"); - } - @Test void basicResponse() { ConfigurableEnvironment environment = emptyEnvironment(); @@ -126,6 +119,15 @@ class EnvironmentEndpointTests { }); } + @Test + void responseWhenPatternIsInvalidThrowsInvalidEndpointRequestException() { + ConfigurableEnvironment environment = emptyEnvironment(); + EnvironmentEndpoint endpoint = new EnvironmentEndpoint(environment, Collections.emptyList(), Show.ALWAYS); + assertThatExceptionOfType(InvalidEndpointRequestException.class).isThrownBy(() -> endpoint.environment("[")) + .withMessageContaining("Failed to parse regular expression: [") + .withCauseInstanceOf(PatternSyntaxException.class); + } + @Test void compositeSourceIsHandledCorrectly() { ConfigurableEnvironment environment = emptyEnvironment();