CVE-2025-49015
Description
The Couchbase .NET SDK (client library) before 3.7.1 does not properly enable hostname verification for TLS certificates. In fact, the SDK was also using IP addresses instead of hostnames due to a configuration option that was incorrectly enabled by default.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Couchbase .NET SDK before 3.7.1 fails to validate TLS hostnames, enabling man-in-the-middle attacks.
Vulnerability
Overview
CVE-2025-49015 describes a security flaw in the Couchbase .NET SDK (client library) versions prior to 3.7.1. The SDK did not properly enable hostname verification for TLS certificates, and it also incorrectly used IP addresses instead of hostnames due to a misconfigured default option [1][2]. This means that during TLS handshake, the client does not check whether the certificate presented by the server matches the intended hostname, breaking a fundamental TLS protection.
Exploitation
Scenario
An attacker in a position to intercept network traffic (e.g., on the same network segment or via DNS spoofing) can present a valid TLS certificate for a different domain or an IP address that passes basic certificate chain validation but fails hostname matching [2]. The SDK’s failure to verify the hostname means the client will accept this certificate and proceed with the connection, enabling the attacker to decrypt and modify traffic.
Impact
Successful exploitation allows a man-in-the-middle (MITM) attacker to read, modify, or inject data into communications between the .NET application and the Couchbase server. This could lead to exposure of sensitive data, credential theft, or unauthorized actions on the database, depending on the application’s privileges.
Mitigation
The issue is fixed in the Couchbase .NET SDK version 3.7.1. The fix ensures hostname verification is enforced and removes the problematic default that used IP addresses for certificate validation [4]. Users should upgrade to SDK 3.7.1 or later. No workarounds are documented; upgrading is the recommended mitigation.
AI Insight generated on May 19, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
CouchbaseNetClientNuGet | >= 0 | — |
Affected products
2- Couchbase/.NET SDKdescription
Patches
104d1679b2178NCBC-3993: Fail on certificate name failure when not ignored.
5 files changed · +156 −62
src/Couchbase/Core/IO/Authentication/X509/CertificateFactory.cs+2 −20 modified@@ -83,37 +83,20 @@ public static ICertificateFactory GetCertificatesFromStore(CertificateStoreSearc /// <remarks> /// This in-memory certificate does not work on .NET Framework (legacy) clients. /// </remarks> - [Compatibility.InterfaceStability(Compatibility.Level.Volatile)] + [InterfaceStability(Level.Volatile)] internal static readonly X509Certificate2 CapellaCaCert = new X509Certificate2( rawData: System.Text.Encoding.ASCII.GetBytes(CapellaCaCertPem), password: (string?)null); /// <summary> /// Default CA Certificates included with the SDK. /// </summary> - [Compatibility.InterfaceStability(Compatibility.Level.Volatile)] + [InterfaceStability(Level.Volatile)] public static readonly IReadOnlyList<X509Certificate2> DefaultCertificates = new List<X509Certificate2>() { CapellaCaCert, }; - [InterfaceStability(Level.Volatile)] - public static bool ValidatorWithIgnoreNameMismatch(object sender, X509Certificate? certificate, X509Chain? chain, SslPolicyErrors sslPolicyErrors, ILogger? logger = null, IRedactor? redactor = null) - { - sslPolicyErrors = WithoutNameMismatch(sslPolicyErrors, logger); - - if (sslPolicyErrors == SslPolicyErrors.None) - { - logger?.LogDebug("X509 Validation passed with ignore name mismatch."); - return true; - } - else - { - logger?.LogWarning("X509 Validation failed: {errors}", sslPolicyErrors); - return false; - } - } - [InterfaceStability(Level.Volatile)] public static SslPolicyErrors WithoutNameMismatch(SslPolicyErrors errors, ILogger? logger = null) { @@ -122,7 +105,6 @@ public static SslPolicyErrors WithoutNameMismatch(SslPolicyErrors errors, ILogge // clear the name mismatch logger?.LogDebug("Clearing certificate name mismatch error."); errors &= ~SslPolicyErrors.RemoteCertificateNameMismatch; - errors &= ~SslPolicyErrors.RemoteCertificateChainErrors; } return errors;
src/Couchbase/Core/IO/Connections/CallbackCreator.cs+76 −0 added@@ -0,0 +1,76 @@ +using System; +using System.Net.Security; +using System.Security.Cryptography.X509Certificates; +using Couchbase.Core.IO.Authentication.X509; +using Couchbase.Core.Logging; +using Microsoft.Extensions.Logging; + +namespace Couchbase.Core.IO.Connections; + +#nullable enable + +internal class CallbackCreator +{ + private readonly bool _ignoreNameMismatch; + ILogger<object> _sslLogger; + private readonly IRedactor _redactor; + private X509Certificate2Collection? _certs; + + public CallbackCreator( + bool ignoreNameMismatch, + ILogger<object> sslLogger, + IRedactor redactor, + X509Certificate2Collection? certs + ) + { + _ignoreNameMismatch = ignoreNameMismatch; + _sslLogger = sslLogger ?? throw new ArgumentNullException(nameof(sslLogger)); + _redactor = redactor; + _certs = certs; + } + + public bool Callback(object sender, X509Certificate? certificate, X509Chain? chain, + SslPolicyErrors sslPolicyErrors) + { + + certificate = certificate ?? throw new ArgumentNullException(nameof(certificate)); + chain = chain ?? throw new ArgumentNullException(nameof(chain)); + + if (sslPolicyErrors == SslPolicyErrors.None) + { + _sslLogger.LogDebug("X509 Validation passed"); + return true; + } + + if (!_ignoreNameMismatch) + { + if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateNameMismatch) != + SslPolicyErrors.None) + { + _sslLogger.LogInformation( + "X509 Certificate name mismatch error."); // and possibly other issues + return false; + } + } + else + { + if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateNameMismatch) != + SslPolicyErrors.None) + { + _sslLogger.LogDebug("X509 Ignoring Certificate name mismatch error."); + } + } + + if (_certs != null) + { + var customCertsCallback = + CertificateFactory.GetValidatorWithPredefinedCertificates(_certs, _sslLogger, + _redactor); + return customCertsCallback(sender, certificate, chain, sslPolicyErrors); + } + + var defaultCallback = + CertificateFactory.GetValidatorWithDefaultCertificates(_sslLogger, _redactor); + return defaultCallback(sender, certificate, chain, sslPolicyErrors); + } +}
src/Couchbase/Core/IO/Connections/ConnectionFactory.cs+3 −17 modified@@ -131,23 +131,9 @@ public async Task<IConnection> CreateAndConnectAsync(HostEndpointWithPort hostEn RemoteCertificateValidationCallback? certValidationCallback = _clusterOptions.KvCertificateCallbackValidation; if (certValidationCallback == null) { - certValidationCallback = (sender, certificate, chain, sslPolicyErrors) => - { - if (_clusterOptions.KvIgnoreRemoteCertificateNameMismatch - && CertificateFactory.ValidatorWithIgnoreNameMismatch(sender, certificate, chain, sslPolicyErrors, _sslLogger, _redactor)) - { - return true; - } - - if (certs != null) - { - var customCertsCallback = CertificateFactory.GetValidatorWithPredefinedCertificates(certs, _sslLogger, _redactor); - return customCertsCallback(sender, certificate, chain, sslPolicyErrors); - } - - var defaultCallback = CertificateFactory.GetValidatorWithDefaultCertificates(_sslLogger, _redactor); - return defaultCallback(sender, certificate, chain, sslPolicyErrors); - }; + CallbackCreator callbackCreator = new CallbackCreator(_clusterOptions.KvIgnoreRemoteCertificateNameMismatch, _sslLogger, _redactor, certs); + certValidationCallback = (__sender,__certificate, __chain, __sslPolicyErrors) => + callbackCreator.Callback(__sender, __certificate, __chain, __sslPolicyErrors); } var sslStream = new SslStream(new NetworkStream(socket, true), false,
src/Couchbase/Core/IO/HTTP/CouchbaseHttpClientFactory.cs+8 −25 modified@@ -9,6 +9,7 @@ using System.Security.Cryptography.X509Certificates; using Couchbase.Core.Exceptions; using Couchbase.Core.IO.Authentication.X509; +using Couchbase.Core.IO.Connections; using Couchbase.Core.Logging; using Couchbase.Utils; using Microsoft.Extensions.Logging; @@ -151,23 +152,9 @@ private HttpMessageHandler CreateClientHandler() RemoteCertificateValidationCallback? certValidationCallback = _context.ClusterOptions.HttpCertificateCallbackValidation; if (certValidationCallback == null) { - certValidationCallback = (sender, certificate, chain, sslPolicyErrors) => - { - if (_context.ClusterOptions.HttpIgnoreRemoteCertificateMismatch - && CertificateFactory.ValidatorWithIgnoreNameMismatch(sender, certificate, chain, sslPolicyErrors)) - { - return true; - } - - if (certs != null) - { - var customCertsCallback = CertificateFactory.GetValidatorWithPredefinedCertificates(certs, _logger, _redactor); - return customCertsCallback(sender, certificate, chain, sslPolicyErrors); - } - - var callback = CertificateFactory.GetValidatorWithDefaultCertificates(_logger, _redactor); - return callback(sender, certificate, chain, sslPolicyErrors); - }; + CallbackCreator callbackCreator = new CallbackCreator( _context.ClusterOptions.HttpIgnoreRemoteCertificateMismatch, _logger, _redactor, certs); + certValidationCallback = certValidationCallback = (__sender, __certificate, __chain, __sslPolicyErrors) => + callbackCreator.Callback(__sender, __certificate, __chain, __sslPolicyErrors); } handler.SslOptions.RemoteCertificateValidationCallback = certValidationCallback; @@ -216,7 +203,7 @@ private HttpMessageHandler CreateClientHandler() } #if !NETCOREAPP3_1_OR_GREATER - private static Func<HttpRequestMessage, X509Certificate, X509Chain, SslPolicyErrors, bool> + private Func<HttpRequestMessage, X509Certificate, X509Chain, SslPolicyErrors, bool> CreateCertificateValidator(ClusterOptions clusterOptions) { bool OnCertificateValidation(HttpRequestMessage request, X509Certificate certificate, @@ -225,14 +212,10 @@ bool OnCertificateValidation(HttpRequestMessage request, X509Certificate certifi var callback = clusterOptions.HttpCertificateCallbackValidation; if (callback == null) { - if (clusterOptions.HttpIgnoreRemoteCertificateMismatch) - { - return CertificateFactory.ValidatorWithIgnoreNameMismatch(request, certificate, chain, sslPolicyErrors); - } - - return sslPolicyErrors == SslPolicyErrors.None; + CallbackCreator callbackCreator = new CallbackCreator(clusterOptions.HttpIgnoreRemoteCertificateMismatch, _logger, _redactor, null); + callback = (__sender, __certificate, __chain, __sslPolicyErrors) => + callbackCreator.Callback(__sender, __certificate, __chain, __sslPolicyErrors); } - return callback(request, certificate, chain, sslPolicyErrors); }
tests/Couchbase.IntegrationTests/ClusterTests.cs+67 −0 modified@@ -1,6 +1,9 @@ + using System; +using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; +using Couchbase.Core.IO.Authentication.X509; using Couchbase.Diagnostics; using Couchbase.IntegrationTests.Fixtures; using Couchbase.IntegrationTests.Utils; @@ -255,6 +258,70 @@ public async Task Test_Cloud_Default() }*/ } + [Fact (Skip = "Certificate tests Need manual setup and running. Comment out the Skip() to run")] + public async Task Test_Certificates() + { + // Taken from the code given in the Capella UI for connecting with the SDK. + // This example should work without ignoring certificate name mismatches. + // to cause it to fail, use a hostname different from that in the certificate + // i.e. if the name in the certificate is IP:127.0.0.1, use localhost instead. + // Log at Debug and search the log file for X509 + /// tail -f ./tests/Couchbase.IntegrationTests/bin/Debug/net8.0/Logs/myapp-20250401.txt | grep X509 + + // Update this to your cluster + var endpoint = "127.0.0.1"; + var bucketName = "travel-sample"; + + // In the cloud dashboard, go to Clusters -> <your cluster> -> Connect -> Database Access -> Manage Credentials + var username = "clientuser"; + var password = "password"; + // User Input ends here. + + // default without overriding any callbacks. + { + // Initialize the Connection + var opts = new ClusterOptions().WithCredentials(username, password); + opts.EnableTls = true; + opts.ForceIpAsTargetHost = false; + opts.KvIgnoreRemoteCertificateNameMismatch = false; + opts.HttpIgnoreRemoteCertificateMismatch = false; + X509Certificate2[] certs = new X509Certificate2[1]; + const string capemPath = "/Users/michaelreiche/ca.pem"; + certs[0] = new X509Certificate2(capemPath); + opts.WithX509CertificateFactory(CertificateFactory.FromCertificates(certs)); + + IServiceCollection serviceCollection = new ServiceCollection(); + serviceCollection.AddLogging(builder => builder + .AddFilter(level => level >= LogLevel.Trace) + ); + + var loggerFactory = serviceCollection.BuildServiceProvider() + .GetService<ILoggerFactory>(); + loggerFactory.AddFile("Logs/myapp-{Date}.txt", LogLevel.Debug); + opts.WithLogging(loggerFactory); + + var cluster = + await Couchbase.Cluster.ConnectAsync("couchbases://" + endpoint, opts); + + await cluster.WaitUntilReadyAsync(TimeSpan.FromSeconds(5)); + var bucket = await cluster.BucketAsync(bucketName); + var collection = bucket.DefaultCollection(); + + + // Store a Document + var upsertResult = await collection.UpsertAsync("king_arthur", new + { + Name = "Arthur", + Email = "kingarthur@couchbase.com", + Interests = new[] { "Holy Grail", "African Swallows" } + }); + + // Load the Document and print it + var getResult = await collection.GetAsync("king_arthur"); + Console.WriteLine(getResult.ContentAs<dynamic>()); + } + } + [Fact] public async Task Test_Default_Scope_Collection_Legacy() {
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
7- github.com/advisories/GHSA-px2c-r924-mwccghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-49015ghsaADVISORY
- docs.couchbase.com/server/current/release-notes/relnotes.htmlghsaWEB
- forums.couchbase.com/tags/securityghsaWEB
- github.com/couchbase/couchbase-net-client/commit/04d1679b2178f922036be6e595b3d91f972c5ba3ghsaWEB
- www.couchbase.com/alertsghsaWEB
- www.couchbase.com/alerts/mitre
News mentions
0No linked articles in our index yet.