From ee6a1798b5b4a4d8956330b0dbf2cfd480eb426b Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 1 Sep 2026 11:09:36 +0200 Subject: [PATCH 1/5] C#: Add explicit class with dependabot configuration. --- .../DependabotProxy.cs | 24 +++++++------------ .../DependabotProxyConfiguration.cs | 15 ++++++++++++ .../IDependabotProxyConfiguration.cs | 21 ++++++++++++++++ 3 files changed, 44 insertions(+), 16 deletions(-) create mode 100644 csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependabotProxyConfiguration.cs create mode 100644 csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/IDependabotProxyConfiguration.cs diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependabotProxy.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependabotProxy.cs index 08b142219a97..7166d18c6694 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependabotProxy.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependabotProxy.cs @@ -39,23 +39,18 @@ public record class RegistryConfig(string Type, string URL); // instance of `DependabotProxy` on those platforms. if (SystemBuildActions.Instance.IsWindows() || SystemBuildActions.Instance.IsMacOs()) return null; - // Obtain and store the address of the Dependabot proxy, if available. - var host = Environment.GetEnvironmentVariable(EnvironmentVariableNames.ProxyHost); - var port = Environment.GetEnvironmentVariable(EnvironmentVariableNames.ProxyPort); + var proxyConfig = new DependabotProxyConfiguration(); - if (string.IsNullOrWhiteSpace(host) || string.IsNullOrWhiteSpace(port)) + if (string.IsNullOrWhiteSpace(proxyConfig.Host) || string.IsNullOrWhiteSpace(proxyConfig.Port)) { logger.LogInfo("No Dependabot proxy credentials are configured."); return null; } - var result = new DependabotProxy(host, port); + var result = new DependabotProxy(proxyConfig.Host, proxyConfig.Port); logger.LogInfo($"Dependabot proxy configured at {result.Address}"); - // Obtain and store the proxy's certificate, if available. - var cert = Environment.GetEnvironmentVariable(EnvironmentVariableNames.ProxyCertificate); - - if (!string.IsNullOrWhiteSpace(cert)) + if (!string.IsNullOrWhiteSpace(proxyConfig.Certificate)) { var certDirPath = new DirectoryInfo(Path.Join(tempWorkingDirectory.DirInfo.FullName, ".dependabot-proxy")); Directory.CreateDirectory(certDirPath.FullName); @@ -64,24 +59,21 @@ public record class RegistryConfig(string Type, string URL); var certFile = new FileInfo(result.CertificatePath); using var writer = certFile.CreateText(); - writer.Write(cert); + writer.Write(proxyConfig.Certificate); writer.Close(); logger.LogInfo($"Stored Dependabot proxy certificate at {result.CertificatePath}"); - result.Certificate = X509Certificate2.CreateFromPem(cert); + result.Certificate = X509Certificate2.CreateFromPem(proxyConfig.Certificate); } - // Try to obtain the list of private registry URLs. - var registryURLs = Environment.GetEnvironmentVariable(EnvironmentVariableNames.ProxyURLs); - - if (!string.IsNullOrWhiteSpace(registryURLs)) + if (!string.IsNullOrWhiteSpace(proxyConfig.RegistryURLs)) { try { // The value of the environment variable should be a JSON array of objects, such as: // [ { "type": "nuget_feed", "url": "https://nuget.pkg.github.com/org/index.json" } ] - var array = JsonConvert.DeserializeObject>(registryURLs); + var array = JsonConvert.DeserializeObject>(proxyConfig.RegistryURLs); if (array is not null) { foreach (RegistryConfig config in array) diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependabotProxyConfiguration.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependabotProxyConfiguration.cs new file mode 100644 index 000000000000..2d81f94aea2c --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependabotProxyConfiguration.cs @@ -0,0 +1,15 @@ +using System; + +namespace Semmle.Extraction.CSharp.DependencyFetching +{ + public class DependabotProxyConfiguration : IDependabotProxyConfiguration + { + public string? Host { get; } = Environment.GetEnvironmentVariable(EnvironmentVariableNames.ProxyHost); + + public string? Port { get; } = Environment.GetEnvironmentVariable(EnvironmentVariableNames.ProxyPort); + + public string? Certificate { get; } = Environment.GetEnvironmentVariable(EnvironmentVariableNames.ProxyCertificate); + + public string? RegistryURLs { get; } = Environment.GetEnvironmentVariable(EnvironmentVariableNames.ProxyURLs); + } +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/IDependabotProxyConfiguration.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/IDependabotProxyConfiguration.cs new file mode 100644 index 000000000000..c67ee4fc39df --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/IDependabotProxyConfiguration.cs @@ -0,0 +1,21 @@ +using System; + +namespace Semmle.Extraction.CSharp.DependencyFetching +{ + public interface IDependabotProxyConfiguration + { + // The host of the Dependabot proxy, if available. + string? Host { get; } + + // The port of the Dependabot proxy, if available. + string? Port { get; } + + // The certificate of the Dependabot proxy, if available. + string? Certificate { get; } + + // The list of package registries that are configured for the proxy, if any. + // The value of the environment variable should be a JSON array of objects, such as: + // [ { "type": "nuget_feed", "url": "https://nuget.pkg.github.com/org/index.json" } ] + string? RegistryURLs { get; } + } +} From 68d8351fee65443e4ab87ec2a840c455e183adee Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 1 Sep 2026 12:42:03 +0200 Subject: [PATCH 2/5] C#: Move some logic into the DependabotProxy object construction. --- .../DependabotProxy.cs | 90 +++++++++---------- 1 file changed, 43 insertions(+), 47 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependabotProxy.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependabotProxy.cs index 7166d18c6694..c298877da8a6 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependabotProxy.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependabotProxy.cs @@ -18,76 +18,54 @@ public class DependabotProxy : IDependabotProxy /// The URL of the package registry. public record class RegistryConfig(string Type, string URL); - private readonly string host; - private readonly string port; - public string Address { get; } - public HashSet RegistryURLs { get; } + public HashSet RegistryURLs { get; } = []; public string? CertificatePath { get; private set; } public X509Certificate2? Certificate { get; private set; } - internal static IDependabotProxy? GetDependabotProxy( - ILogger logger, IDiagnosticsWriter diagnosticsWriter, TemporaryDirectory tempWorkingDirectory) + private DependabotProxy(IDependabotProxyConfiguration config, ILogger logger, TemporaryDirectory tempWorkingDirectory) { - // Setting HTTP(S)_PROXY and SSL_CERT_FILE have no effect on Windows or macOS, - // but we would still end up using the Dependabot proxy to check for feed reachability. - // This would result in us discovering that the feeds are reachable, but `dotnet` would - // fail to connect to them. To prevent this from happening, we do not initialise an - // instance of `DependabotProxy` on those platforms. - if (SystemBuildActions.Instance.IsWindows() || SystemBuildActions.Instance.IsMacOs()) return null; - - var proxyConfig = new DependabotProxyConfiguration(); + Address = $"http://{config.Host}:{config.Port}"; - if (string.IsNullOrWhiteSpace(proxyConfig.Host) || string.IsNullOrWhiteSpace(proxyConfig.Port)) - { - logger.LogInfo("No Dependabot proxy credentials are configured."); - return null; - } - - var result = new DependabotProxy(proxyConfig.Host, proxyConfig.Port); - logger.LogInfo($"Dependabot proxy configured at {result.Address}"); - - if (!string.IsNullOrWhiteSpace(proxyConfig.Certificate)) + if (!string.IsNullOrWhiteSpace(config.Certificate)) { var certDirPath = new DirectoryInfo(Path.Join(tempWorkingDirectory.DirInfo.FullName, ".dependabot-proxy")); Directory.CreateDirectory(certDirPath.FullName); - result.CertificatePath = Path.Join(certDirPath.FullName, "proxy.crt"); - var certFile = new FileInfo(result.CertificatePath); + CertificatePath = Path.Join(certDirPath.FullName, "proxy.crt"); + var certFile = new FileInfo(CertificatePath); using var writer = certFile.CreateText(); - writer.Write(proxyConfig.Certificate); + writer.Write(config.Certificate); writer.Close(); - logger.LogInfo($"Stored Dependabot proxy certificate at {result.CertificatePath}"); + logger.LogInfo($"Stored Dependabot proxy certificate at {CertificatePath}"); - result.Certificate = X509Certificate2.CreateFromPem(proxyConfig.Certificate); + Certificate = X509Certificate2.CreateFromPem(config.Certificate); } - if (!string.IsNullOrWhiteSpace(proxyConfig.RegistryURLs)) + if (!string.IsNullOrWhiteSpace(config.RegistryURLs)) { try { - // The value of the environment variable should be a JSON array of objects, such as: - // [ { "type": "nuget_feed", "url": "https://nuget.pkg.github.com/org/index.json" } ] - var array = JsonConvert.DeserializeObject>(proxyConfig.RegistryURLs); + var array = JsonConvert.DeserializeObject>(config.RegistryURLs); if (array is not null) { - foreach (RegistryConfig config in array) + foreach (RegistryConfig registry in array) { // The array contains all configured private registries, not just ones for C#. // We ignore the non-C# ones here. - if (!config.Type.Equals("nuget_feed")) + if (!registry.Type.Equals("nuget_feed")) { - logger.LogDebug($"Ignoring registry at '{config.URL}' since it is not of type 'nuget_feed'."); + logger.LogDebug($"Ignoring registry at '{registry.URL}' since it is not of type 'nuget_feed'."); continue; } - logger.LogInfo($"Found private registry at '{config.URL}'"); - result.RegistryURLs.Add(config.URL); + logger.LogInfo($"Found private registry at '{registry.URL}'"); + RegistryURLs.Add(registry.URL); } } } @@ -96,6 +74,32 @@ public record class RegistryConfig(string Type, string URL); logger.LogError($"Unable to parse '{EnvironmentVariableNames.ProxyURLs}': {ex.Message}"); } } + } + + + internal static IDependabotProxy? GetDependabotProxy( + ILogger logger, IDiagnosticsWriter diagnosticsWriter, TemporaryDirectory tempWorkingDirectory) + { + // Setting HTTP(S)_PROXY and SSL_CERT_FILE have no effect on Windows or macOS, + // but we would still end up using the Dependabot proxy to check for feed reachability. + // This would result in us discovering that the feeds are reachable, but `dotnet` would + // fail to connect to them. To prevent this from happening, we do not initialise an + // instance of `DependabotProxy` on those platforms. + if (SystemBuildActions.Instance.IsWindows() || SystemBuildActions.Instance.IsMacOs()) + { + return null; + } + + var proxyConfig = new DependabotProxyConfiguration(); + + if (string.IsNullOrWhiteSpace(proxyConfig.Host) || string.IsNullOrWhiteSpace(proxyConfig.Port)) + { + logger.LogInfo("No Dependabot proxy credentials are configured."); + return null; + } + + var result = new DependabotProxy(proxyConfig, logger, tempWorkingDirectory); + logger.LogInfo($"Dependabot proxy configured at {result.Address}"); // Emit a diagnostic for the discovered private registries, so that it is easy // for users to see that they were picked up. @@ -117,17 +121,9 @@ public record class RegistryConfig(string Type, string URL); return result; } - private DependabotProxy(string host, string port) - { - this.host = host; - this.port = port; - this.Address = $"http://{this.host}:{this.port}"; - this.RegistryURLs = new HashSet(); - } - public void Dispose() { - this.Certificate?.Dispose(); + Certificate?.Dispose(); } } } From b3ae7ff0d5af8a093605859c2d2810c526c9467c Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 1 Sep 2026 14:48:29 +0200 Subject: [PATCH 3/5] C#: Minor re-write to enable OS independant testing of dependabot proxy object creation. --- .../DependabotProxy.cs | 10 ++++++---- .../DependencyManager.cs | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependabotProxy.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependabotProxy.cs index c298877da8a6..a80593f85a55 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependabotProxy.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependabotProxy.cs @@ -76,9 +76,7 @@ private DependabotProxy(IDependabotProxyConfiguration config, ILogger logger, Te } } - - internal static IDependabotProxy? GetDependabotProxy( - ILogger logger, IDiagnosticsWriter diagnosticsWriter, TemporaryDirectory tempWorkingDirectory) + internal static IDependabotProxy? Make(ILogger logger, IDiagnosticsWriter diagnosticsWriter, TemporaryDirectory tempWorkingDirectory) { // Setting HTTP(S)_PROXY and SSL_CERT_FILE have no effect on Windows or macOS, // but we would still end up using the Dependabot proxy to check for feed reachability. @@ -90,8 +88,12 @@ private DependabotProxy(IDependabotProxyConfiguration config, ILogger logger, Te return null; } - var proxyConfig = new DependabotProxyConfiguration(); + return MakeAux(new DependabotProxyConfiguration(), logger, diagnosticsWriter, tempWorkingDirectory); + } + internal static IDependabotProxy? MakeAux( + IDependabotProxyConfiguration proxyConfig, ILogger logger, IDiagnosticsWriter diagnosticsWriter, TemporaryDirectory tempWorkingDirectory) + { if (string.IsNullOrWhiteSpace(proxyConfig.Host) || string.IsNullOrWhiteSpace(proxyConfig.Port)) { logger.LogInfo("No Dependabot proxy credentials are configured."); diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependencyManager.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependencyManager.cs index 707fabbf83fb..a985947c0c12 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependencyManager.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependencyManager.cs @@ -106,7 +106,7 @@ void exitCallback(int ret, string msg, bool silent) return BuildScript.Success; }).Run(SystemBuildActions.Instance, startCallback, exitCallback); - dependabotProxy = DependabotProxy.GetDependabotProxy(logger, diagnosticsWriter, tempWorkingDirectory); + dependabotProxy = DependabotProxy.Make(logger, diagnosticsWriter, tempWorkingDirectory); try { From 8583ecc639eb1a199e0f13b3e4298e997320e26c Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 1 Sep 2026 14:48:58 +0200 Subject: [PATCH 4/5] C#: Add DependabotProxy unit-tests. --- .../DependabotProxy.cs | 185 ++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 csharp/extractor/Semmle.Extraction.Tests/DependabotProxy.cs diff --git a/csharp/extractor/Semmle.Extraction.Tests/DependabotProxy.cs b/csharp/extractor/Semmle.Extraction.Tests/DependabotProxy.cs new file mode 100644 index 000000000000..7aadae00b4ea --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.Tests/DependabotProxy.cs @@ -0,0 +1,185 @@ +using Xunit; +using System; +using System.IO; +using Semmle.Extraction.CSharp.DependencyFetching; +using Semmle.Util; + +namespace Semmle.Extraction.Tests +{ + public class DependabotConfigurationStub : IDependabotProxyConfiguration + { + public string? Host { get; set; } + public string? Port { get; set; } + public string? Certificate { get; set; } + public string? RegistryURLs { get; set; } + } + + public class DiagnosticsWriterStub : IDiagnosticsWriter + { + public void AddEntry(Semmle.Util.DiagnosticMessage entry) { } + public void Dispose() { } + } + + public class DependabotProxyTests + { + private static TemporaryDirectory MakeTemporaryDirectory() + { + var tmp = Path.Join(Path.GetTempPath(), "DependabotProxyTests", Guid.NewGuid().ToString()); + return new TemporaryDirectory(tmp, "testing", new LoggerStub()); + } + + [Fact] + public void TestDependabotProxyCreation1() + { + // Setup + var config = new DependabotConfigurationStub + { + Host = "my.private.server", + Port = "", + }; + + // Execute + using var tempWorkingDirectory = MakeTemporaryDirectory(); + using var proxy = DependabotProxy.MakeAux(config, new LoggerStub(), new DiagnosticsWriterStub(), tempWorkingDirectory); + + // Verify + Assert.Null(proxy); + } + + [Fact] + public void TestDependabotProxyCreation2() + { + // Setup + var config = new DependabotConfigurationStub + { + Port = "8080", + }; + + // Execute + using var tempWorkingDirectory = MakeTemporaryDirectory(); + using var proxy = DependabotProxy.MakeAux(config, new LoggerStub(), new DiagnosticsWriterStub(), tempWorkingDirectory); + + // Verify + Assert.Null(proxy); + } + + private const string ExampleCertificate = """ + -----BEGIN CERTIFICATE----- + MIIFJTCCAw2gAwIBAgIUDImU6YnuAqJ1QuRp+OpJQPnPu6wwDQYJKoZIhvcNAQEL + BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI2MDkwMTEyMjUzMVoXDTI3MDkw + MTEyMjUzMVowFDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEF + AAOCAg8AMIICCgKCAgEAnlp7yQ1VuocMwIZWlCle3bEM86+1ED6BFfPFpIrRhfUT + c+5IvPng8TIZPO4mROp5G9YDZfOtXW2bwktyZNUhsBcxqUT1lmXit21vc5W9Gxx5 + 4G8nyF4/FcjFkmxkZifxiUCdBceDcE7+kx2itq/a7gLPlyTzvz5etu1nHEC3Jg/y + TVhAwdwysgAo9WymFCczDa2ga6nOPBOaxwLnoPl9041KSu5oIo9QC0Im+US1R18Q + /mXa+wkmjf+bYAkE/pZie8z8Q7h9yppTngGzkoDEebFYyaMr8MXlFdWS8f/eMwSp + iMFSsmlCqgUbA672APxzOcuSMMYrblzGkvZp23qbNjwQuQKlgAYBTSGltLv4U8JF + ePNcgDCY6RG55rNvF1gk1L2h25jcw1LX6fSvQGCOkzNmP03AhqZBUigO1Zt0zLwi + K4m0bH7nPLJFEN6tI3tybyZeC2RVyiSHvOkgx35Qj8RQ3XMVkImJNBYOMc2MkmMZ + ux6XMiHqXCON4zaWuWSovciZeMAQAspCrzVDLH6p2DWEfw/zDfQNU3iLk21sZGei + 0GKzs8zrxUcqOU9V4Cnm+7JJ6eqS72f1+wX0ROb3djC6KgCE/NaHqo4apiI3K+CH + T0rVRsJIHyT39YO1c1I1vhAKRSH5kQVe3qRfIT/AuaDLQY6WqGPzrOkem78sjtsC + AwEAAaNvMG0wHQYDVR0OBBYEFK0DP5MD6mhEcdcm346uwoPL2NFGMB8GA1UdIwQY + MBaAFK0DP5MD6mhEcdcm346uwoPL2NFGMA8GA1UdEwEB/wQFMAMBAf8wGgYDVR0R + BBMwEYIJbG9jYWxob3N0hwR/AAABMA0GCSqGSIb3DQEBCwUAA4ICAQCc5u8qNHHG + kONjfvq7Denq6QaEt4dZZDDODAvgUzZnnBjEhgrp7zfxtbyU/I0+DWnKQMKA9wPM + ktiFGd0lldEqoT+E7b0kN124lBGqZ/uYkhsWZ0Nc5dD+UB9oJszwOc5KNuquOnr6 + SbsfXVm4yLvVLXl67c0jvqvRgGg9/6Q6eMzohW6abMdbYhS28/DsJhCea/dV3+L1 + oVJ3O/A8e86m174ZCGE8s9UtnVYylBkAryDqaaQLdOBQ2C7uxdRAUNHSIa2JlqUc + 5+cod8lFojKb74hbgj6wkXyajsFttqYMh7CeASsnjZXDQ4MC3DqqDVCZuNvJ85Rt + ya3Tljp4Ln2AAAoKC3REUeU8PQqpk1vVIj0FSr3RvBTvwzyNfWFVqyBiXTATuV9n + 6AemqqXo5MZrHHeRaSTF8A70Jxbt9yx75xQxp3O3tdEL1Mxbl9X7c/hizOfLbeHH + IkAgzALQgi87Zbf2tOhRwH5NrB4ijyUUfovRHUwzsZOoTNqlVeNzbDRVbegx9V99 + /3vwNZgpStGl/JYhN9qY5hJKnC64ltMvuNGpLeJCGyFkrtFS8gKkgR7VKrGo7h3+ + Zo8rz8TFjP7RmSgQbrmFuPqNOGXzPidu2sMMFacKV7Rn4bEtHzW3MDhqVD4w/pGD + L0xpnWjzLYltVjz8mo07yh+zQ10G71Cl1w== + -----END CERTIFICATE----- + """; + + [Fact] + public void TestDependabotProxyCertificate() + { + // Setup + var config = new DependabotConfigurationStub + { + Port = "8080", + Host = "my.private.server", + Certificate = ExampleCertificate + }; + + // Execute + using var tempWorkingDirectory = MakeTemporaryDirectory(); + using var proxy = DependabotProxy.MakeAux(config, new LoggerStub(), new DiagnosticsWriterStub(), tempWorkingDirectory); + + // Verify + Assert.NotNull(proxy); + Assert.Equal("http://my.private.server:8080", proxy.Address); + Assert.NotNull(proxy.Certificate); + Assert.NotNull(proxy.CertificatePath); + } + + [Fact] + public void TestDependabotRegistryUrls1() + { + // Setup + var config = new DependabotConfigurationStub + { + Port = "8080", + Host = "my.private.server", + RegistryURLs = "Doesn't parse as a JSON list" + }; + + // Execute + using var tempWorkingDirectory = MakeTemporaryDirectory(); + using var proxy = DependabotProxy.MakeAux(config, new LoggerStub(), new DiagnosticsWriterStub(), tempWorkingDirectory); + + // Verify + Assert.NotNull(proxy); + Assert.Equal([], proxy.RegistryURLs); + } + + [Fact] + public void TestDependabotRegistryUrls2() + { + // Setup + var config = new DependabotConfigurationStub + { + Port = "8080", + Host = "my.private.server", + RegistryURLs = "[ { \"type\": \"nuget_feed\", \"url\": \"https://nuget.pkg.github.com/org/index.json\" } ]" + }; + + // Execute + using var tempWorkingDirectory = MakeTemporaryDirectory(); + using var proxy = DependabotProxy.MakeAux(config, new LoggerStub(), new DiagnosticsWriterStub(), tempWorkingDirectory); + + // Verify + Assert.NotNull(proxy); + Assert.Equal([ + "https://nuget.pkg.github.com/org/index.json" + ], proxy.RegistryURLs); + } + + [Fact] + public void TestDependabotRegistryUrls3() + { + // Setup + var config = new DependabotConfigurationStub + { + Port = "8080", + Host = "my.private.server", + RegistryURLs = "[ { \"type\": \"nuget_feed\", \"url\": \"https://example.com/org/index.json\" }, { \"type\": \"wrong_type\", \"url\": \"https://nuget.pkg.github.com/org/index.json\" } ]" + }; + + // Execute + using var tempWorkingDirectory = MakeTemporaryDirectory(); + using var proxy = DependabotProxy.MakeAux(config, new LoggerStub(), new DiagnosticsWriterStub(), tempWorkingDirectory); + + // Verify + Assert.NotNull(proxy); + Assert.Equal([ + "https://example.com/org/index.json" + ], proxy.RegistryURLs); + } + } +} From 2dc8ef98001ab505e1da87ab83e72c19bcc8a39d Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Wed, 2 Sep 2026 16:30:35 +0200 Subject: [PATCH 5/5] C#: Address some review comments. --- .../DependabotProxy.cs | 11 ++++++--- .../DependabotProxy.cs | 24 +++++++++---------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependabotProxy.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependabotProxy.cs index a80593f85a55..3bf843d3fa2c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependabotProxy.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependabotProxy.cs @@ -88,15 +88,20 @@ private DependabotProxy(IDependabotProxyConfiguration config, ILogger logger, Te return null; } - return MakeAux(new DependabotProxyConfiguration(), logger, diagnosticsWriter, tempWorkingDirectory); + return Make(new DependabotProxyConfiguration(), logger, diagnosticsWriter, tempWorkingDirectory); } - internal static IDependabotProxy? MakeAux( + /// + /// Creates an instance of the Dependabot proxy using the specified configuration. + /// Returns null if the proxy cannot be created. + /// This overload is exposed primarily to enable platform-independent unit testing. + /// + internal static IDependabotProxy? Make( IDependabotProxyConfiguration proxyConfig, ILogger logger, IDiagnosticsWriter diagnosticsWriter, TemporaryDirectory tempWorkingDirectory) { if (string.IsNullOrWhiteSpace(proxyConfig.Host) || string.IsNullOrWhiteSpace(proxyConfig.Port)) { - logger.LogInfo("No Dependabot proxy credentials are configured."); + logger.LogDebug("No Dependabot proxy credentials are configured."); return null; } diff --git a/csharp/extractor/Semmle.Extraction.Tests/DependabotProxy.cs b/csharp/extractor/Semmle.Extraction.Tests/DependabotProxy.cs index 7aadae00b4ea..9c8c762f5989 100644 --- a/csharp/extractor/Semmle.Extraction.Tests/DependabotProxy.cs +++ b/csharp/extractor/Semmle.Extraction.Tests/DependabotProxy.cs @@ -34,13 +34,13 @@ public void TestDependabotProxyCreation1() // Setup var config = new DependabotConfigurationStub { - Host = "my.private.server", + Host = "localhost", Port = "", }; // Execute using var tempWorkingDirectory = MakeTemporaryDirectory(); - using var proxy = DependabotProxy.MakeAux(config, new LoggerStub(), new DiagnosticsWriterStub(), tempWorkingDirectory); + using var proxy = DependabotProxy.Make(config, new LoggerStub(), new DiagnosticsWriterStub(), tempWorkingDirectory); // Verify Assert.Null(proxy); @@ -57,7 +57,7 @@ public void TestDependabotProxyCreation2() // Execute using var tempWorkingDirectory = MakeTemporaryDirectory(); - using var proxy = DependabotProxy.MakeAux(config, new LoggerStub(), new DiagnosticsWriterStub(), tempWorkingDirectory); + using var proxy = DependabotProxy.Make(config, new LoggerStub(), new DiagnosticsWriterStub(), tempWorkingDirectory); // Verify Assert.Null(proxy); @@ -103,17 +103,17 @@ public void TestDependabotProxyCertificate() var config = new DependabotConfigurationStub { Port = "8080", - Host = "my.private.server", + Host = "localhost", Certificate = ExampleCertificate }; // Execute using var tempWorkingDirectory = MakeTemporaryDirectory(); - using var proxy = DependabotProxy.MakeAux(config, new LoggerStub(), new DiagnosticsWriterStub(), tempWorkingDirectory); + using var proxy = DependabotProxy.Make(config, new LoggerStub(), new DiagnosticsWriterStub(), tempWorkingDirectory); // Verify Assert.NotNull(proxy); - Assert.Equal("http://my.private.server:8080", proxy.Address); + Assert.Equal("http://localhost:8080", proxy.Address); Assert.NotNull(proxy.Certificate); Assert.NotNull(proxy.CertificatePath); } @@ -125,13 +125,13 @@ public void TestDependabotRegistryUrls1() var config = new DependabotConfigurationStub { Port = "8080", - Host = "my.private.server", + Host = "localhost", RegistryURLs = "Doesn't parse as a JSON list" }; // Execute using var tempWorkingDirectory = MakeTemporaryDirectory(); - using var proxy = DependabotProxy.MakeAux(config, new LoggerStub(), new DiagnosticsWriterStub(), tempWorkingDirectory); + using var proxy = DependabotProxy.Make(config, new LoggerStub(), new DiagnosticsWriterStub(), tempWorkingDirectory); // Verify Assert.NotNull(proxy); @@ -145,13 +145,13 @@ public void TestDependabotRegistryUrls2() var config = new DependabotConfigurationStub { Port = "8080", - Host = "my.private.server", + Host = "localhost", RegistryURLs = "[ { \"type\": \"nuget_feed\", \"url\": \"https://nuget.pkg.github.com/org/index.json\" } ]" }; // Execute using var tempWorkingDirectory = MakeTemporaryDirectory(); - using var proxy = DependabotProxy.MakeAux(config, new LoggerStub(), new DiagnosticsWriterStub(), tempWorkingDirectory); + using var proxy = DependabotProxy.Make(config, new LoggerStub(), new DiagnosticsWriterStub(), tempWorkingDirectory); // Verify Assert.NotNull(proxy); @@ -167,13 +167,13 @@ public void TestDependabotRegistryUrls3() var config = new DependabotConfigurationStub { Port = "8080", - Host = "my.private.server", + Host = "localhost", RegistryURLs = "[ { \"type\": \"nuget_feed\", \"url\": \"https://example.com/org/index.json\" }, { \"type\": \"wrong_type\", \"url\": \"https://nuget.pkg.github.com/org/index.json\" } ]" }; // Execute using var tempWorkingDirectory = MakeTemporaryDirectory(); - using var proxy = DependabotProxy.MakeAux(config, new LoggerStub(), new DiagnosticsWriterStub(), tempWorkingDirectory); + using var proxy = DependabotProxy.Make(config, new LoggerStub(), new DiagnosticsWriterStub(), tempWorkingDirectory); // Verify Assert.NotNull(proxy);