diff --git a/src/LaunchDarkly.EventSource/EventSourceService.cs b/src/LaunchDarkly.EventSource/EventSourceService.cs index ac0b543..87bb171 100644 --- a/src/LaunchDarkly.EventSource/EventSourceService.cs +++ b/src/LaunchDarkly.EventSource/EventSourceService.cs @@ -199,7 +199,20 @@ private HttpRequestMessage CreateHttpRequestMessage(Uri uri, string lastEventId) { foreach (var item in _configuration.RequestHeaders) { - request.Headers.Add(item.Key, item.Value); + try + { + request.Headers.Add(item.Key, item.Value); + } + catch (FormatException) + { + // Avoid showing the Authorization header value in the exception message + if (item.Key.Equals("Authorization", StringComparison.OrdinalIgnoreCase)) + { + throw new FormatException("The Authorization header is invalid."); + } + + throw; + } } } diff --git a/test/LaunchDarkly.EventSource.Tests/EventSourceHttpBehaviorTest.cs b/test/LaunchDarkly.EventSource.Tests/EventSourceHttpBehaviorTest.cs index 5cd147b..fb1189b 100644 --- a/test/LaunchDarkly.EventSource.Tests/EventSourceHttpBehaviorTest.cs +++ b/test/LaunchDarkly.EventSource.Tests/EventSourceHttpBehaviorTest.cs @@ -165,6 +165,37 @@ public void HttpRequestModifier() } } + [Fact] + public async Task MalformedAuthorizationHeaderDoesNotExposeKeyInException() + { + using (var server = HttpServer.Start(EmptyStreamThatStaysOpen)) + { + var taskComplete = new TaskCompletionSource(); + var errorMessage = string.Empty; + + var invalidSdkKey = "\nsecret-api-key-with"; + var headers = new Dictionary { { "Authorization", invalidSdkKey } }; + + using (var es = MakeEventSource(server.Uri, builder => builder.RequestHeaders(headers))) + { + es.Error += (sender, args) => + { + errorMessage = args.Exception.Message; + taskComplete.SetResult(true); + }; + + _ = Task.Run(es.StartAsync); + + // Wait for the error event with a timeout + var timeoutTask = Task.Delay(TimeSpan.FromSeconds(5)); + var completedTask = await Task.WhenAny(taskComplete.Task, timeoutTask); + + Assert.True(completedTask == taskComplete.Task, "Test timed out waiting for error event"); + Assert.DoesNotContain(invalidSdkKey, errorMessage); + } + } + } + [Fact] public async void OpenedEventIncludesHeaders() {