Skip to content

Commit 1870f07

Browse files
committed
Protect against invalid use of profiles
1 parent 6f17bc3 commit 1870f07

File tree

6 files changed

+74
-2
lines changed

6 files changed

+74
-2
lines changed

spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/EnvironmentController.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
import org.springframework.cloud.config.environment.Environment;
3737
import org.springframework.cloud.config.environment.EnvironmentMediaType;
3838
import org.springframework.cloud.config.environment.PropertySource;
39-
import org.springframework.cloud.config.server.support.PathUtils;
4039
import org.springframework.http.HttpHeaders;
4140
import org.springframework.http.HttpStatus;
4241
import org.springframework.http.MediaType;
@@ -51,6 +50,7 @@
5150

5251
import static org.springframework.cloud.config.server.support.EnvironmentPropertySource.prepareEnvironment;
5352
import static org.springframework.cloud.config.server.support.EnvironmentPropertySource.resolvePlaceholders;
53+
import static org.springframework.cloud.config.server.support.PathUtils.isInvalidEncodedLocation;
5454

5555
/**
5656
* @author Dave Syer
@@ -131,6 +131,9 @@ public Environment getEnvironment(String name, String profiles, String label, bo
131131
try {
132132
name = normalize(name);
133133
label = normalize(label);
134+
if (isInvalidEncodedLocation(profiles)) {
135+
throw new InvalidEnvironmentRequestException("Invalid request");
136+
}
134137
Environment environment = this.repository.findOne(name, profiles, label, includeOrigin);
135138
if (!this.acceptEmpty && (environment == null || environment.getPropertySources().isEmpty())) {
136139
throw new EnvironmentNotFoundException("Profile Not found");
@@ -145,7 +148,7 @@ public Environment getEnvironment(String name, String profiles, String label, bo
145148
}
146149

147150
private String normalize(String part) {
148-
if (PathUtils.isInvalidEncodedLocation(part)) {
151+
if (isInvalidEncodedLocation(part)) {
149152
throw new InvalidEnvironmentRequestException("Invalid request");
150153
}
151154
return Environment.normalize(part);

spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/resource/ResourceController.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.springframework.cloud.config.environment.Environment;
3232
import org.springframework.cloud.config.server.encryption.ResourceEncryptor;
3333
import org.springframework.cloud.config.server.environment.EnvironmentRepository;
34+
import org.springframework.cloud.config.server.environment.InvalidEnvironmentRequestException;
3435
import org.springframework.core.io.Resource;
3536
import org.springframework.http.HttpHeaders;
3637
import org.springframework.http.MediaType;
@@ -48,6 +49,7 @@
4849

4950
import static org.springframework.cloud.config.server.support.EnvironmentPropertySource.prepareEnvironment;
5051
import static org.springframework.cloud.config.server.support.EnvironmentPropertySource.resolvePlaceholders;
52+
import static org.springframework.cloud.config.server.support.PathUtils.isInvalidEncodedLocation;
5153

5254
/**
5355
* 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
142144
boolean resolvePlaceholders, String acceptedCharset) throws IOException {
143145
name = Environment.normalize(name);
144146
label = Environment.normalize(label);
147+
if (isInvalidEncodedLocation(profile)) {
148+
throw new InvalidEnvironmentRequestException("Invalid request");
149+
}
145150
Resource resource = this.resourceRepository.findOne(name, profile, label, path);
146151
if (checkNotModified(request, resource)) {
147152
// Content was not modified. Just return.
@@ -213,6 +218,9 @@ private synchronized byte[] binary(ServletWebRequest request, String name, Strin
213218
String path) throws IOException {
214219
name = Environment.normalize(name);
215220
label = Environment.normalize(label);
221+
if (isInvalidEncodedLocation(profile)) {
222+
throw new InvalidEnvironmentRequestException("Invalid request");
223+
}
216224
Resource resource = this.resourceRepository.findOne(name, profile, label, path);
217225
if (checkNotModified(request, resource)) {
218226
// Content was not modified. Just return.

spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/AbstractScmAccessor.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
3939
import org.springframework.util.FileSystemUtils;
4040
import org.springframework.util.StringUtils;
41+
import org.springframework.web.util.UriComponents;
42+
import org.springframework.web.util.UriComponentsBuilder;
4143

4244
/**
4345
* Base class for components that want to access a source control management system.
@@ -150,9 +152,21 @@ public void setUri(String uri) {
150152
// If there's no context path add one
151153
uri = uri + "/";
152154
}
155+
validateNoTemplateInAuthority(uri);
153156
this.uri = uri;
154157
}
155158

159+
private void validateNoTemplateInAuthority(String urlTemplate) {
160+
UriComponents components = UriComponentsBuilder.fromUriString(urlTemplate).build();
161+
// If the port is templated this call will throw an Exception
162+
components.getPort();
163+
String host = components.getHost();
164+
if (host != null && (host.contains("{") || host.contains("}"))) {
165+
throw new IllegalArgumentException("Template placeholders not allowed in host: " + urlTemplate);
166+
}
167+
168+
}
169+
156170
public File getBasedir() {
157171
return this.basedir;
158172
}

spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/EnvironmentControllerTests.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,18 @@ public void nameWithPoundEncoded() {
554554
.isInstanceOf(InvalidEnvironmentRequestException.class);
555555
}
556556

557+
@Test
558+
public void invalidProfileTests() {
559+
assertThatThrownBy(() -> this.controller.labelled("application", "bar,..,foo", "label"))
560+
.isInstanceOf(InvalidEnvironmentRequestException.class);
561+
assertThatThrownBy(() -> this.controller.labelled("application", "..", "label"))
562+
.isInstanceOf(InvalidEnvironmentRequestException.class);
563+
assertThatThrownBy(() -> this.controller.labelled("application", "%2e%2e", "label"))
564+
.isInstanceOf(InvalidEnvironmentRequestException.class);
565+
assertThatThrownBy(() -> this.controller.labelled("application", "bar,%2e%2e,foo", "label"))
566+
.isInstanceOf(InvalidEnvironmentRequestException.class);
567+
}
568+
557569
abstract class MockMvcTestCases {
558570

559571
protected MockMvc mvc;

spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentApplicationPlaceholderRepositoryTests.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.springframework.core.env.StandardEnvironment;
3535

3636
import static org.assertj.core.api.Assertions.assertThat;
37+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
3738

3839
/**
3940
* @author Dave Syer
@@ -115,6 +116,15 @@ public void otherMappingRepo() {
115116
assertVersion(environment);
116117
}
117118

119+
@Test
120+
void invalidAuthorityTests() {
121+
assertThatThrownBy(() -> createRepository("test", "*-config-repo", "http://{profile}:8080/test1-config-repo"))
122+
.isInstanceOf(IllegalArgumentException.class);
123+
assertThatThrownBy(
124+
() -> createRepository("test", "*-config-repo", "http://localhost:{profile}/test1-config-repo"))
125+
.isInstanceOf(IllegalStateException.class);
126+
}
127+
118128
@Test
119129
@Disabled("not supported yet (placeholders in search paths with lists)")
120130
public void profilesInSearchPaths() {

spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/resource/ResourceControllerTests.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.springframework.boot.WebApplicationType;
2929
import org.springframework.boot.builder.SpringApplicationBuilder;
3030
import org.springframework.cloud.config.server.encryption.ResourceEncryptor;
31+
import org.springframework.cloud.config.server.environment.InvalidEnvironmentRequestException;
3132
import org.springframework.cloud.config.server.environment.NativeEnvironmentProperties;
3233
import org.springframework.cloud.config.server.environment.NativeEnvironmentRepository;
3334
import org.springframework.cloud.config.server.environment.NativeEnvironmentRepositoryTests;
@@ -37,6 +38,7 @@
3738
import org.springframework.web.context.request.ServletWebRequest;
3839

3940
import static org.assertj.core.api.Assertions.assertThat;
41+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
4042
import static org.mockito.ArgumentMatchers.any;
4143
import static org.mockito.ArgumentMatchers.anyString;
4244
import static org.mockito.Mockito.mock;
@@ -368,4 +370,27 @@ public void setSearchLocationsAppendSlashByConstructor() {
368370
assertThat(repo.getSearchLocations()[0]).isEqualTo("classpath:/test/");
369371
}
370372

373+
@Test
374+
public void invalidProfileTests() {
375+
assertThatThrownBy(
376+
() -> this.controller.retrieve("application", "bar,..,foo", "label", "template.json", true, "UTF-8"))
377+
.isInstanceOf(InvalidEnvironmentRequestException.class);
378+
assertThatThrownBy(() -> this.controller.binary("application", "bar,..,foo", "label", "template.json"))
379+
.isInstanceOf(InvalidEnvironmentRequestException.class);
380+
assertThatThrownBy(() -> this.controller.retrieve("application", "..", "label", "template.json", true, "UTF-8"))
381+
.isInstanceOf(InvalidEnvironmentRequestException.class);
382+
assertThatThrownBy(() -> this.controller.binary("application", "..", "label", "template.json"))
383+
.isInstanceOf(InvalidEnvironmentRequestException.class);
384+
assertThatThrownBy(
385+
() -> this.controller.retrieve("application", "%2e%2e", "label", "template.json", true, "UTF-8"))
386+
.isInstanceOf(InvalidEnvironmentRequestException.class);
387+
assertThatThrownBy(() -> this.controller.binary("application", "%2e%2e", "label", "template.json"))
388+
.isInstanceOf(InvalidEnvironmentRequestException.class);
389+
assertThatThrownBy(() -> this.controller.retrieve("application", "bar,%2e%2e,foo", "label", "template.json",
390+
true, "UTF-8"))
391+
.isInstanceOf(InvalidEnvironmentRequestException.class);
392+
assertThatThrownBy(() -> this.controller.binary("application", "bar,%2e%2e,foo", "label", "template.json"))
393+
.isInstanceOf(InvalidEnvironmentRequestException.class);
394+
}
395+
371396
}

0 commit comments

Comments
 (0)