Skip to content

SqlConnection.Open() leaks Password in exception message when server is unreachable #25

@priyankatiwari08

Description

@priyankatiwari08

Describe the bug

SqlConnection.Open() includes the full connection string (including Password=...) in the exception message when the server is unreachable. This leaks credentials into application logs, error monitoring tools (Sentry, Application Insights, etc.), and crash dumps.

To reproduce

using Microsoft.Data.SqlClient;

var builder = new SqlConnectionStringBuilder
{
    DataSource = "nonexistent-server.example.com",
    InitialCatalog = "mydb",
    UserID = "sa",
    Password = "MySecretP@ssw0rd!",
    ConnectTimeout = 5,
    Encrypt = SqlConnectionEncryptOption.Optional
};

try
{
    using var conn = new SqlConnection(builder.ConnectionString);
    conn.Open();
}
catch (SqlException ex)
{
    Console.WriteLine(ex.Message);
    // Output includes: "...Password=MySecretP@ssw0rd!..."
    // The password is visible in the exception message
}

Expected behavior

Exception messages from SqlConnection.Open() should never include the Password value from the connection string. The password should be redacted (e.g., replaced with ****) or the connection string should be omitted entirely from exception messages.

ADO.NET's DbConnectionStringBuilder.ConnectionString property already redacts passwords by default when PersistSecurityInfo=false, but the internal error path in SqlInternalConnectionTds constructs its own error message using the raw connection options, bypassing this redaction.

Actual behavior

The full connection string including Password=MySecretP@ssw0rd! appears in the SqlException.Message text, which typically gets:

  • Written to ILogger / console logs
  • Captured by error monitoring (App Insights, Sentry, Datadog)
  • Stored in Windows Event Log
  • Included in crash dumps

Further technical details

Microsoft.Data.SqlClient version: 6.0.0
Target framework: .NET 8.0
SQL Server version: N/A (server unreachable, issue is in client error handling)
Operating system: Windows 11 23H2

The issue appears to be in SqlInternalConnectionTds.LoginNoFailover() and SqlInternalConnectionTds.LoginWithFailover() where error messages are constructed using ConnectionOptions without going through the redaction path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions