VYPR
Medium severity5.3NVD Advisory· Published Jul 17, 2024· Updated Apr 15, 2026

CVE-2024-40636

CVE-2024-40636

Description

Steeltoe is an open source project that provides a collection of libraries that helps users build production-grade cloud-native applications using externalized configuration, service discovery, distributed tracing, application management, and more. When utilizing multiple Eureka server service URLs with basic auth and encountering an issue with fetching the service registry, an error is logged with the Eureka server service URLs but only the first URL is masked. The code in question is _logger.LogError(e, "FetchRegistry Failed for Eureka service urls: {EurekaServerServiceUrls}", new Uri(ClientConfig.EurekaServerServiceUrls).ToMaskedString()); in the DiscoveryClient.cs file which may leak credentials into logs. This issue has been addressed in version 3.2.8 of the Steeltoe.Discovery.Eureka nuget package.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
Steeltoe.Discovery.EurekaNuGet
< 3.2.83.2.8
Steeltoe.Discovery.EurekaBaseNuGet
<= 2.5.5
Steeltoe.Discovery.ClientCoreNuGet
>= 0
Steeltoe.Discovery.ClientAutofacNuGet
<= 2.5.5

Patches

1
c5d4a94e90cc

Fix Eureka URI masking

https://github.com/SteeltoeOSS/SteeltoeBart KoelmanJul 8, 2024via ghsa
4 files changed · +38 60
  • src/Common/src/Common/Extensions/UriExtensions.cs+24 25 modified
    @@ -4,29 +4,48 @@
     
     using System;
     using System.Collections.Generic;
    +using System.Linq;
     using System.Net;
     
     namespace Steeltoe.Common.Extensions;
     
     public static class UriExtensions
     {
    -    public static string ToMaskedString(this Uri source)
    +    private static readonly char[] _uriSeparatorChar = { ',' };
    +
    +    /// <summary>
    +    /// Parse a querystring into a dictionary of key value pairs
    +    /// </summary>
    +    /// <param name="querystring">The querystring to parse</param>
    +    /// <returns>Pairs of keys and values</returns>
    +    public static Dictionary<string, string> ParseQuerystring(string querystring)
         {
    -        if (source == null)
    +        var result = new Dictionary<string, string>();
    +        foreach (var pair in querystring.Split('&'))
             {
    -            throw new ArgumentNullException(nameof(source));
    +            if (!string.IsNullOrEmpty(pair))
    +            {
    +                var kvp = pair.Split('=');
    +                result.Add(WebUtility.UrlDecode(kvp[0]), WebUtility.UrlDecode(kvp[1]));
    +            }
             }
     
    -        return source.ToMaskedUri().ToString();
    +        return result;
         }
     
    -    public static Uri ToMaskedUri(this Uri source)
    +    public static string ToMaskedString(this Uri source)
         {
             if (source == null)
             {
                 throw new ArgumentNullException(nameof(source));
             }
     
    +        var uris = source.ToString();
    +        return string.Join(",", uris.Split(_uriSeparatorChar, StringSplitOptions.RemoveEmptyEntries).Select(uri => new Uri(uri).ToMaskedUri().ToString()));
    +    }
    +
    +    private static Uri ToMaskedUri(this Uri source)
    +    {
             if (string.IsNullOrEmpty(source.UserInfo))
             {
                 return source;
    @@ -42,24 +61,4 @@ public static Uri ToMaskedUri(this Uri source)
     
             return builder.Uri;
         }
    -
    -    /// <summary>
    -    /// Parse a querystring into a dictionary of key value pairs
    -    /// </summary>
    -    /// <param name="querystring">The querystring to parse</param>
    -    /// <returns>Pairs of keys and values</returns>
    -    public static Dictionary<string, string> ParseQuerystring(string querystring)
    -    {
    -        var result = new Dictionary<string, string>();
    -        foreach (var pair in querystring.Split('&'))
    -        {
    -            if (!string.IsNullOrEmpty(pair))
    -            {
    -                var kvp = pair.Split('=');
    -                result.Add(WebUtility.UrlDecode(kvp[0]), WebUtility.UrlDecode(kvp[1]));
    -            }
    -        }
    -
    -        return result;
    -    }
     }
    \ No newline at end of file
    
  • src/Common/test/Common.Test/Extensions/UriExtensionsTest.cs+4 26 modified
    @@ -10,30 +10,19 @@ namespace Steeltoe.Common.Test.Extensions;
     
     public class UriExtensionsTest
     {
    -    [Fact]
    -    public void MaskExistingBasicAuthenticationToString()
    -    {
    -        var uri = new Uri("http://username:password@www.example.com/");
    -        var expected = "http://****:****@www.example.com/";
    -
    -        var masked = uri.ToMaskedString();
    -
    -        Assert.Equal(expected, masked);
    -    }
    -
         [Fact]
         public void MaskExistingBasicAuthentication()
         {
    -        var uri = new Uri("http://username:password@www.example.com/");
    -        var expected = new Uri("http://****:****@www.example.com/");
    +        var uri = new Uri("http://username:password@www.example.com/,http://user2:pass2@www.other.com/");
    +        var expected = "http://****:****@www.example.com/,http://****:****@www.other.com/";
     
    -        var masked = uri.ToMaskedUri();
    +        var masked = uri.ToMaskedString();
     
             Assert.Equal(expected, masked);
         }
     
         [Fact]
    -    public void DontMaskStringIfNotBasicAuthenticationExists()
    +    public void DontMaskIfNotBasicAuthenticationExists()
         {
             var uri = new Uri("http://www.example.com/");
             var expected = uri.ToString();
    @@ -42,15 +31,4 @@ public void DontMaskStringIfNotBasicAuthenticationExists()
     
             Assert.Equal(expected, masked);
         }
    -
    -    [Fact]
    -    public void DontMaskUriIfNotBasicAuthenticationExists()
    -    {
    -        var uri = new Uri("http://www.example.com/");
    -        var expected = new Uri(uri.ToString());
    -
    -        var masked = uri.ToMaskedUri();
    -
    -        Assert.Equal(expected, masked);
    -    }
     }
    \ No newline at end of file
    
  • src/Discovery/src/Eureka/DiscoveryClient.cs+2 1 modified
    @@ -322,7 +322,8 @@ protected internal async T.Task<bool> FetchRegistryAsync(bool fullUpdate)
             catch (Exception e)
             {
                 // Log
    -            _logger.LogError(e, "FetchRegistry Failed for Eureka service urls: {EurekaServerServiceUrls}", new Uri(ClientConfig.EurekaServerServiceUrls).ToMaskedString());
    +            var masked = new Uri(ClientConfig.EurekaServerServiceUrls).ToMaskedString();
    +            _logger.LogError(e, "FetchRegistry Failed for Eureka service urls: {EurekaServerServiceUrls}", masked);
                 return false;
             }
     
    
  • src/Discovery/src/Eureka/Transport/EurekaHttpClient.cs+8 8 modified
    @@ -132,7 +132,7 @@ private async Task<EurekaHttpResponse> RegisterAsyncInternal(InstanceInfo info)
                 }
                 catch (Exception e)
                 {
    -                _logger?.LogError(e, "RegisterAsync Failed, request was made to {requestUri}, retry: {retry}", requestUri.ToMaskedUri(), retry);
    +                _logger?.LogError(e, "RegisterAsync Failed, request was made to {requestUri}, retry: {retry}", requestUri.ToMaskedString(), retry);
                 }
                 finally
                 {
    @@ -250,7 +250,7 @@ private async Task<EurekaHttpResponse<InstanceInfo>> SendHeartBeatAsyncInternal(
                 }
                 catch (Exception e)
                 {
    -                _logger?.LogError(e, "SendHeartBeatAsync Failed, request was made to {requestUri}", requestUri.ToMaskedUri());
    +                _logger?.LogError(e, "SendHeartBeatAsync Failed, request was made to {requestUri}", requestUri.ToMaskedString());
                 }
                 finally
                 {
    @@ -363,7 +363,7 @@ private async Task<EurekaHttpResponse<Application>> GetApplicationAsyncInternal(
                 }
                 catch (Exception e)
                 {
    -                _logger?.LogError(e, "GetApplicationAsync Failed, request was made to {requestUri}", requestUri.ToMaskedUri());
    +                _logger?.LogError(e, "GetApplicationAsync Failed, request was made to {requestUri}", requestUri.ToMaskedString());
                 }
                 finally
                 {
    @@ -460,7 +460,7 @@ private async Task<EurekaHttpResponse> CancelAsyncInternal(string appName, strin
                 }
                 catch (Exception e)
                 {
    -                _logger?.LogError(e, "CancelAsync Failed, request was made to {requestUri}", requestUri.ToMaskedUri());
    +                _logger?.LogError(e, "CancelAsync Failed, request was made to {requestUri}", requestUri.ToMaskedString());
                 }
                 finally
                 {
    @@ -536,7 +536,7 @@ private async Task<EurekaHttpResponse> DeleteStatusOverrideAsyncInternal(string
                 }
                 catch (Exception e)
                 {
    -                _logger?.LogError(e, "DeleteStatusOverrideAsync Failed, request was made to {requestUri}", requestUri.ToMaskedUri());
    +                _logger?.LogError(e, "DeleteStatusOverrideAsync Failed, request was made to {requestUri}", requestUri.ToMaskedString());
                 }
                 finally
                 {
    @@ -613,7 +613,7 @@ private async Task<EurekaHttpResponse> StatusUpdateAsyncInternal(string appName,
                 }
                 catch (Exception e)
                 {
    -                _logger?.LogError(e, "StatusUpdateAsync Failed, request was made to {requestUri}", requestUri.ToMaskedUri());
    +                _logger?.LogError(e, "StatusUpdateAsync Failed, request was made to {requestUri}", requestUri.ToMaskedString());
                 }
                 finally
                 {
    @@ -865,7 +865,7 @@ protected virtual async Task<EurekaHttpResponse<InstanceInfo>> DoGetInstanceAsyn
                 }
                 catch (Exception e)
                 {
    -                _logger?.LogError(e, "DoGetInstanceAsync Failed, request was made to {requestUri}", requestUri.ToMaskedUri());
    +                _logger?.LogError(e, "DoGetInstanceAsync Failed, request was made to {requestUri}", requestUri.ToMaskedString());
                 }
                 finally
                 {
    @@ -945,7 +945,7 @@ protected virtual async Task<EurekaHttpResponse<Applications>> DoGetApplications
                 }
                 catch (Exception e)
                 {
    -                _logger?.LogError(e, "DoGetApplicationsAsync Failed, request was made to {requestUri}", requestUri.ToMaskedUri());
    +                _logger?.LogError(e, "DoGetApplicationsAsync Failed, request was made to {requestUri}", requestUri.ToMaskedString());
                 }
                 finally
                 {
    

Vulnerability mechanics

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

References

4

News mentions

0

No linked articles in our index yet.