Skip to content

Commit c75c67e

Browse files
committed
Additional hardening against special characters in Config Server URL
1 parent 0f57724 commit c75c67e

3 files changed

Lines changed: 42 additions & 23 deletions

File tree

src/Configuration/src/ConfigServer/ConfigServerConfigurationProvider.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -630,15 +630,15 @@ internal Uri BuildConfigServerUri(string serverUri, string? label)
630630

631631
if (!string.IsNullOrEmpty(ClientOptions.Username))
632632
{
633-
uriBuilder.UserName = ClientOptions.Username;
633+
uriBuilder.UserName = WebUtility.UrlEncode(ClientOptions.Username);
634634
}
635635

636636
if (!string.IsNullOrEmpty(ClientOptions.Password))
637637
{
638-
uriBuilder.Password = ClientOptions.Password;
638+
uriBuilder.Password = WebUtility.UrlEncode(ClientOptions.Password);
639639
}
640640

641-
string pathSuffix = $"{ClientOptions.Name}/{WebUtility.UrlEncode(ClientOptions.Environment)}";
641+
string pathSuffix = $"{WebUtility.UrlEncode(ClientOptions.Name)}/{WebUtility.UrlEncode(ClientOptions.Environment)}";
642642

643643
if (!string.IsNullOrWhiteSpace(label))
644644
{
@@ -648,7 +648,7 @@ internal Uri BuildConfigServerUri(string serverUri, string? label)
648648
label = label.Replace("/", "(_)", StringComparison.Ordinal);
649649
}
650650

651-
pathSuffix = $"{pathSuffix}/{label.Trim()}";
651+
pathSuffix = $"{pathSuffix}/{WebUtility.UrlEncode(label)}";
652652
}
653653

654654
if (!uriBuilder.Path.EndsWith('/'))

src/Configuration/test/ConfigServer.Test/ConfigServerConfigurationProviderTest.Settings.cs

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,9 @@ public void GetConfigServerUri_NoLabel()
7979
};
8080

8181
using var provider = new ConfigServerConfigurationProvider(options, null, null, NullLoggerFactory.Instance);
82-
string path = provider.BuildConfigServerUri(options.Uri!, null).ToString();
82+
string uri = provider.BuildConfigServerUri(options.Uri!, null).ToString();
8383

84-
path.Should().Be($"{options.Uri}/{options.Name}/{options.Environment}");
84+
uri.Should().Be($"{options.Uri}/{options.Name}/{options.Environment}");
8585
}
8686

8787
[Fact]
@@ -95,9 +95,9 @@ public void GetConfigServerUri_WithLabel()
9595
};
9696

9797
using var provider = new ConfigServerConfigurationProvider(options, null, null, NullLoggerFactory.Instance);
98-
string path = provider.BuildConfigServerUri(options.Uri!, options.Label).ToString();
98+
string uri = provider.BuildConfigServerUri(options.Uri!, options.Label).ToString();
9999

100-
path.Should().Be($"{options.Uri}/{options.Name}/{options.Environment}/{options.Label}");
100+
uri.Should().Be($"{options.Uri}/{options.Name}/{options.Environment}/{options.Label}");
101101
}
102102

103103
[Fact]
@@ -111,9 +111,9 @@ public void GetConfigServerUri_WithLabelContainingSlash()
111111
};
112112

113113
using var provider = new ConfigServerConfigurationProvider(options, null, null, NullLoggerFactory.Instance);
114-
string path = provider.BuildConfigServerUri(options.Uri!, options.Label).ToString();
114+
string uri = provider.BuildConfigServerUri(options.Uri!, options.Label).ToString();
115115

116-
path.Should().Be($"{options.Uri}/{options.Name}/{options.Environment}/myLabel(_)version");
116+
uri.Should().Be($"{options.Uri}/{options.Name}/{options.Environment}/myLabel(_)version");
117117
}
118118

119119
[Fact]
@@ -127,9 +127,9 @@ public void GetConfigServerUri_WithExtraPathInfo()
127127
};
128128

129129
using var provider = new ConfigServerConfigurationProvider(options, null, null, NullLoggerFactory.Instance);
130-
string path = provider.BuildConfigServerUri(options.Uri, null).ToString();
130+
string uri = provider.BuildConfigServerUri(options.Uri, null).ToString();
131131

132-
path.Should().Be($"http://localhost:9999/myPath/path/{options.Name}/{options.Environment}");
132+
uri.Should().Be($"http://localhost:9999/myPath/path/{options.Name}/{options.Environment}");
133133
}
134134

135135
[Fact]
@@ -143,9 +143,9 @@ public void GetConfigServerUri_WithExtraPathInfo_NoEndingSlash()
143143
};
144144

145145
using var provider = new ConfigServerConfigurationProvider(options, null, null, NullLoggerFactory.Instance);
146-
string path = provider.BuildConfigServerUri(options.Uri, null).ToString();
146+
string uri = provider.BuildConfigServerUri(options.Uri, null).ToString();
147147

148-
path.Should().Be($"http://localhost:9999/myPath/path/{options.Name}/{options.Environment}");
148+
uri.Should().Be($"http://localhost:9999/myPath/path/{options.Name}/{options.Environment}");
149149
}
150150

151151
[Fact]
@@ -159,9 +159,9 @@ public void GetConfigServerUri_NoEndingSlash()
159159
};
160160

161161
using var provider = new ConfigServerConfigurationProvider(options, null, null, NullLoggerFactory.Instance);
162-
string path = provider.BuildConfigServerUri(options.Uri, null).ToString();
162+
string uri = provider.BuildConfigServerUri(options.Uri, null).ToString();
163163

164-
path.Should().Be($"http://localhost:9999/{options.Name}/{options.Environment}");
164+
uri.Should().Be($"http://localhost:9999/{options.Name}/{options.Environment}");
165165
}
166166

167167
[Fact]
@@ -175,9 +175,9 @@ public void GetConfigServerUri_WithEndingSlash()
175175
};
176176

177177
using var provider = new ConfigServerConfigurationProvider(options, null, null, NullLoggerFactory.Instance);
178-
string path = provider.BuildConfigServerUri(options.Uri, null).ToString();
178+
string uri = provider.BuildConfigServerUri(options.Uri, null).ToString();
179179

180-
path.Should().Be($"http://localhost:9999/{options.Name}/{options.Environment}");
180+
uri.Should().Be($"http://localhost:9999/{options.Name}/{options.Environment}");
181181
}
182182

183183
[Fact]
@@ -191,8 +191,27 @@ public void GetConfigServerUri_MultipleEnvironments_EncodesComma()
191191
};
192192

193193
using var provider = new ConfigServerConfigurationProvider(options, null, null, NullLoggerFactory.Instance);
194-
string path = provider.BuildConfigServerUri(options.Uri!, options.Label).ToString();
194+
string uri = provider.BuildConfigServerUri(options.Uri!, options.Label).ToString();
195195

196-
path.Should().Be("http://localhost:8888/myName/one%2Ctwo/demo");
196+
uri.Should().Be("http://localhost:8888/myName/one%2Ctwo/demo");
197+
}
198+
199+
[Fact]
200+
public void GetConfigServerUri_EncodesSpecialCharacters()
201+
{
202+
var options = new ConfigServerClientOptions
203+
{
204+
Name = "my$<>:,\"'Name",
205+
Environment = "@/&?:\"'",
206+
Label = "^&$@#*<>+",
207+
Username = "a\":?'*,b/\\&",
208+
Password = "#&:$<>'/so,\"me"
209+
};
210+
211+
using var provider = new ConfigServerConfigurationProvider(options, null, null, NullLoggerFactory.Instance);
212+
string uri = provider.BuildConfigServerUri(options.Uri!, options.Label).ToString();
213+
214+
uri.Should().Be(
215+
"http://a%22%3A%3F%27*%2Cb%2F%5C%26:%23%26%3A%24%3C%3E%27%2Fso%2C%22me@localhost:8888/my%24<>%3A%2C\"%27Name/%40%2F%26%3F%3A\"%27/^%26%24%40%23*<>%2B");
197216
}
198217
}

src/Discovery/test/HttpClients.Test/RegisterMultipleDiscoveryClientsTest.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -602,8 +602,8 @@ public async Task EurekaWithUsernamePasswordInURL_SendsWithAuthHeader()
602602
}
603603
""";
604604

605-
string username = WebUtility.UrlEncode("u$er?N@me");
606-
string password = WebUtility.UrlEncode(":p@ssw0rd=");
605+
string username = WebUtility.UrlEncode("u$er?,N@me");
606+
string password = WebUtility.UrlEncode(":p@ss,w0rd=");
607607

608608
var appSettings = new Dictionary<string, string?>
609609
{
@@ -619,7 +619,7 @@ public async Task EurekaWithUsernamePasswordInURL_SendsWithAuthHeader()
619619

620620
var handler = new DelegateToMockHttpClientHandler();
621621

622-
handler.Mock.Expect(HttpMethod.Get, "https://api.eureka-server.com/eureka/apps").WithHeaders("Authorization", "Basic dSRlcj9OQG1lOjpwQHNzdzByZD0=")
622+
handler.Mock.Expect(HttpMethod.Get, "https://api.eureka-server.com/eureka/apps").WithHeaders("Authorization", "Basic dSRlcj8sTkBtZTo6cEBzcyx3MHJkPQ==")
623623
.WithHeaders("X-Discovery-AllowRedirect", "false").Respond("application/json", applicationsResponse);
624624

625625
await using WebApplication webApplication = builder.Build();

0 commit comments

Comments
 (0)