VYPR
High severityNVD Advisory· Published Mar 24, 2026· Updated Mar 24, 2026

Spring Cloud Config Profile Substitution Can Allow Unintended Access To Files And Enable SSRF Attacks

CVE-2026-22739

Description

Vulnerability in Spring Cloud when substituting the profile parameter from a request made to the Spring Cloud Config Server configured to the native file system as a backend, because it was possible to access files outside of the configured search directories.This issue affects Spring Cloud: from 3.1.X before 3.1.13, from 4.1.X before 4.1.9, from 4.2.X before 4.2.3, from 4.3.X before 4.3.2, from 5.0.X before 5.0.2.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Spring Cloud Config Server with native backend is vulnerable to path traversal via crafted profile parameters, allowing access to files outside configured search directories.

Vulnerability

Overview

CVE-2026-22739 is a path traversal vulnerability in Spring Cloud Config Server when configured with the native file system as a backend. The flaw resides in how the server handles the profile parameter from incoming requests. By substituting a profile value with directory traversal sequences (e.g., .. or URL-encoded %2e%2e), an attacker can cause the server to access files outside of the intended search directories [2][3]. The official description confirms that the server does not properly validate the profile parameter before using it to locate configuration resources [1].

Exploitation

The attack surface is the HTTP API of the Spring Cloud Config Server. An attacker can exploit this vulnerability by sending a crafted request containing malicious profile parameters such as bar,..,foo or simply ... The commit that fixes the vulnerability includes tests demonstrating that these inputs now result in an InvalidEnvironmentRequestException [3]. No authentication is mentioned as a requirement in the references, indicating that the vulnerable endpoints may be publicly exposed or accessible to any network actor able to reach the server.

Impact

Successful exploitation allows an attacker to read arbitrary files from the server's filesystem, potentially including sensitive configuration data, credentials, or other secrets stored beyond the configured search paths. This could lead to information disclosure and further compromise of the Spring Cloud environment. The vulnerability affects multiple versions: 3.1.x before 3.1.13, 4.1.x before 4.1.9, 4.2.x before 4.2.3, 4.3.x before 4.3.2, and 5.0.x before 5.0.2 [2].

Mitigation

Spring Cloud has released patches in versions 5.0.2 and the respective fixes for older branches [4]. The fix introduces input validation that throws an InvalidEnvironmentRequestException for invalid profile parameters containing traversal sequences [3]. Users are strongly advised to upgrade to the latest secure version for their branch. No workarounds are mentioned in the provided references.

AI Insight generated on May 18, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.springframework.cloud:spring-cloud-config-serverMaven
>= 4.3.0, < 4.3.24.3.2
org.springframework.cloud:spring-cloud-config-serverMaven
>= 5.0.0-M1, < 5.0.25.0.2
org.springframework.cloud:spring-cloud-config-serverMaven
>= 4.2.0, <= 4.2.4
org.springframework.cloud:spring-cloud-config-serverMaven
>= 4.0.0, <= 4.1.7
org.springframework.cloud:spring-cloud-config-serverMaven
<= 3.1.10

Affected products

2

Patches

1
1870f07befd5

Protect against invalid use of profiles

6 files changed · +74 2
  • spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/EnvironmentController.java+5 2 modified
    @@ -36,7 +36,6 @@
     import org.springframework.cloud.config.environment.Environment;
     import org.springframework.cloud.config.environment.EnvironmentMediaType;
     import org.springframework.cloud.config.environment.PropertySource;
    -import org.springframework.cloud.config.server.support.PathUtils;
     import org.springframework.http.HttpHeaders;
     import org.springframework.http.HttpStatus;
     import org.springframework.http.MediaType;
    @@ -51,6 +50,7 @@
     
     import static org.springframework.cloud.config.server.support.EnvironmentPropertySource.prepareEnvironment;
     import static org.springframework.cloud.config.server.support.EnvironmentPropertySource.resolvePlaceholders;
    +import static org.springframework.cloud.config.server.support.PathUtils.isInvalidEncodedLocation;
     
     /**
      * @author Dave Syer
    @@ -131,6 +131,9 @@ public Environment getEnvironment(String name, String profiles, String label, bo
     		try {
     			name = normalize(name);
     			label = normalize(label);
    +			if (isInvalidEncodedLocation(profiles)) {
    +				throw new InvalidEnvironmentRequestException("Invalid request");
    +			}
     			Environment environment = this.repository.findOne(name, profiles, label, includeOrigin);
     			if (!this.acceptEmpty && (environment == null || environment.getPropertySources().isEmpty())) {
     				throw new EnvironmentNotFoundException("Profile Not found");
    @@ -145,7 +148,7 @@ public Environment getEnvironment(String name, String profiles, String label, bo
     	}
     
     	private String normalize(String part) {
    -		if (PathUtils.isInvalidEncodedLocation(part)) {
    +		if (isInvalidEncodedLocation(part)) {
     			throw new InvalidEnvironmentRequestException("Invalid request");
     		}
     		return Environment.normalize(part);
    
  • spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/resource/ResourceController.java+8 0 modified
    @@ -31,6 +31,7 @@
     import org.springframework.cloud.config.environment.Environment;
     import org.springframework.cloud.config.server.encryption.ResourceEncryptor;
     import org.springframework.cloud.config.server.environment.EnvironmentRepository;
    +import org.springframework.cloud.config.server.environment.InvalidEnvironmentRequestException;
     import org.springframework.core.io.Resource;
     import org.springframework.http.HttpHeaders;
     import org.springframework.http.MediaType;
    @@ -48,6 +49,7 @@
     
     import static org.springframework.cloud.config.server.support.EnvironmentPropertySource.prepareEnvironment;
     import static org.springframework.cloud.config.server.support.EnvironmentPropertySource.resolvePlaceholders;
    +import static org.springframework.cloud.config.server.support.PathUtils.isInvalidEncodedLocation;
     
     /**
      * An HTTP endpoint for serving up templated plain text resources from an underlying
    @@ -142,6 +144,9 @@ synchronized String retrieve(ServletWebRequest request, String name, String prof
     			boolean resolvePlaceholders, String acceptedCharset) throws IOException {
     		name = Environment.normalize(name);
     		label = Environment.normalize(label);
    +		if (isInvalidEncodedLocation(profile)) {
    +			throw new InvalidEnvironmentRequestException("Invalid request");
    +		}
     		Resource resource = this.resourceRepository.findOne(name, profile, label, path);
     		if (checkNotModified(request, resource)) {
     			// Content was not modified. Just return.
    @@ -213,6 +218,9 @@ private synchronized byte[] binary(ServletWebRequest request, String name, Strin
     			String path) throws IOException {
     		name = Environment.normalize(name);
     		label = Environment.normalize(label);
    +		if (isInvalidEncodedLocation(profile)) {
    +			throw new InvalidEnvironmentRequestException("Invalid request");
    +		}
     		Resource resource = this.resourceRepository.findOne(name, profile, label, path);
     		if (checkNotModified(request, resource)) {
     			// Content was not modified. Just return.
    
  • spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/AbstractScmAccessor.java+14 0 modified
    @@ -38,6 +38,8 @@
     import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
     import org.springframework.util.FileSystemUtils;
     import org.springframework.util.StringUtils;
    +import org.springframework.web.util.UriComponents;
    +import org.springframework.web.util.UriComponentsBuilder;
     
     /**
      * Base class for components that want to access a source control management system.
    @@ -150,9 +152,21 @@ public void setUri(String uri) {
     			// If there's no context path add one
     			uri = uri + "/";
     		}
    +		validateNoTemplateInAuthority(uri);
     		this.uri = uri;
     	}
     
    +	private void validateNoTemplateInAuthority(String urlTemplate) {
    +		UriComponents components = UriComponentsBuilder.fromUriString(urlTemplate).build();
    +		// If the port is templated this call will throw an Exception
    +		components.getPort();
    +		String host = components.getHost();
    +		if (host != null && (host.contains("{") || host.contains("}"))) {
    +			throw new IllegalArgumentException("Template placeholders not allowed in host: " + urlTemplate);
    +		}
    +
    +	}
    +
     	public File getBasedir() {
     		return this.basedir;
     	}
    
  • spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/EnvironmentControllerTests.java+12 0 modified
    @@ -554,6 +554,18 @@ public void nameWithPoundEncoded() {
     			.isInstanceOf(InvalidEnvironmentRequestException.class);
     	}
     
    +	@Test
    +	public void invalidProfileTests() {
    +		assertThatThrownBy(() -> this.controller.labelled("application", "bar,..,foo", "label"))
    +			.isInstanceOf(InvalidEnvironmentRequestException.class);
    +		assertThatThrownBy(() -> this.controller.labelled("application", "..", "label"))
    +			.isInstanceOf(InvalidEnvironmentRequestException.class);
    +		assertThatThrownBy(() -> this.controller.labelled("application", "%2e%2e", "label"))
    +			.isInstanceOf(InvalidEnvironmentRequestException.class);
    +		assertThatThrownBy(() -> this.controller.labelled("application", "bar,%2e%2e,foo", "label"))
    +			.isInstanceOf(InvalidEnvironmentRequestException.class);
    +	}
    +
     	abstract class MockMvcTestCases {
     
     		protected MockMvc mvc;
    
  • spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentApplicationPlaceholderRepositoryTests.java+10 0 modified
    @@ -34,6 +34,7 @@
     import org.springframework.core.env.StandardEnvironment;
     
     import static org.assertj.core.api.Assertions.assertThat;
    +import static org.assertj.core.api.Assertions.assertThatThrownBy;
     
     /**
      * @author Dave Syer
    @@ -115,6 +116,15 @@ public void otherMappingRepo() {
     		assertVersion(environment);
     	}
     
    +	@Test
    +	void invalidAuthorityTests() {
    +		assertThatThrownBy(() -> createRepository("test", "*-config-repo", "http://{profile}:8080/test1-config-repo"))
    +			.isInstanceOf(IllegalArgumentException.class);
    +		assertThatThrownBy(
    +				() -> createRepository("test", "*-config-repo", "http://localhost:{profile}/test1-config-repo"))
    +			.isInstanceOf(IllegalStateException.class);
    +	}
    +
     	@Test
     	@Disabled("not supported yet (placeholders in search paths with lists)")
     	public void profilesInSearchPaths() {
    
  • spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/resource/ResourceControllerTests.java+25 0 modified
    @@ -28,6 +28,7 @@
     import org.springframework.boot.WebApplicationType;
     import org.springframework.boot.builder.SpringApplicationBuilder;
     import org.springframework.cloud.config.server.encryption.ResourceEncryptor;
    +import org.springframework.cloud.config.server.environment.InvalidEnvironmentRequestException;
     import org.springframework.cloud.config.server.environment.NativeEnvironmentProperties;
     import org.springframework.cloud.config.server.environment.NativeEnvironmentRepository;
     import org.springframework.cloud.config.server.environment.NativeEnvironmentRepositoryTests;
    @@ -37,6 +38,7 @@
     import org.springframework.web.context.request.ServletWebRequest;
     
     import static org.assertj.core.api.Assertions.assertThat;
    +import static org.assertj.core.api.Assertions.assertThatThrownBy;
     import static org.mockito.ArgumentMatchers.any;
     import static org.mockito.ArgumentMatchers.anyString;
     import static org.mockito.Mockito.mock;
    @@ -368,4 +370,27 @@ public void setSearchLocationsAppendSlashByConstructor() {
     		assertThat(repo.getSearchLocations()[0]).isEqualTo("classpath:/test/");
     	}
     
    +	@Test
    +	public void invalidProfileTests() {
    +		assertThatThrownBy(
    +				() -> this.controller.retrieve("application", "bar,..,foo", "label", "template.json", true, "UTF-8"))
    +			.isInstanceOf(InvalidEnvironmentRequestException.class);
    +		assertThatThrownBy(() -> this.controller.binary("application", "bar,..,foo", "label", "template.json"))
    +			.isInstanceOf(InvalidEnvironmentRequestException.class);
    +		assertThatThrownBy(() -> this.controller.retrieve("application", "..", "label", "template.json", true, "UTF-8"))
    +			.isInstanceOf(InvalidEnvironmentRequestException.class);
    +		assertThatThrownBy(() -> this.controller.binary("application", "..", "label", "template.json"))
    +			.isInstanceOf(InvalidEnvironmentRequestException.class);
    +		assertThatThrownBy(
    +				() -> this.controller.retrieve("application", "%2e%2e", "label", "template.json", true, "UTF-8"))
    +			.isInstanceOf(InvalidEnvironmentRequestException.class);
    +		assertThatThrownBy(() -> this.controller.binary("application", "%2e%2e", "label", "template.json"))
    +			.isInstanceOf(InvalidEnvironmentRequestException.class);
    +		assertThatThrownBy(() -> this.controller.retrieve("application", "bar,%2e%2e,foo", "label", "template.json",
    +				true, "UTF-8"))
    +			.isInstanceOf(InvalidEnvironmentRequestException.class);
    +		assertThatThrownBy(() -> this.controller.binary("application", "bar,%2e%2e,foo", "label", "template.json"))
    +			.isInstanceOf(InvalidEnvironmentRequestException.class);
    +	}
    +
     }
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.