VYPR
Moderate severityNVD Advisory· Published Jun 18, 2025· Updated Jun 18, 2025

CVE-2025-49015

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.

PackageAffected versionsPatched versions
CouchbaseNetClientNuGet
>= 0

Affected products

2

Patches

1
04d1679b2178

NCBC-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

News mentions

0

No linked articles in our index yet.