Don't hard-code TLS/SSL protocol versions
Matches methods setting ServicePointManager.SecurityProtocol, HttpClientHandler.SslProtocols, SslClientAuthenticationOptions.EnabledSslProtocols, Kestrel HttpsConnectionAdapterOptions.SslProtocols, or calling an SslStream.Authenticate... overload with an explicit SslProtocols. Microsoft's guidance since .NET Framework 4.7 / .NET Core is to leave the protocol at SystemDefault / None so that the operating system picks the strongest version available and drops SSL 3.0, TLS 1.0 and TLS 1.1 as they are retired: https://learn.microsoft.com/dotnet/framework/network-programming/tls
This is CWE-326 Inadequate Encryption Strength when the pinned list includes an obsolete version.
Flagged Code
This is CWE-326 Inadequate Encryption Strength when the pinned list includes an obsolete version.
Flagged Code
public HttpClient CreateClient() {
// flagged: freezes the application on TLS 1.2 and blocks TLS 1.3
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var handler = new HttpClientHandler { SslProtocols = SslProtocols.Tls12 }; // flagged
return new HttpClient(handler);
}
Fixed Codepublic HttpClient CreateClient() {
// Target .NET Framework 4.7+ or .NET Core and leave the protocol to the OS
// (SystemDefault): the strongest version is negotiated, retired ones drop out.
return new HttpClient(new HttpClientHandler());
}How to fix
Remove the assignment (or set SecurityProtocolType.SystemDefault / SslProtocols.None) and target .NET Framework 4.7+ or .NET Core, so the OS controls protocol selection. If a peer requires a specific version, isolate that configuration and suppress the issue with a justification.
CQLinq source
This rule is written in CQLinq, C# LINQ over the NDepend code model. It ships with every new NDepend project: you can read it, adapt it, or use it as a starting point for your own custom rules.
// <Name>Don't hard-code TLS/SSL protocol versions</Name>
// <Id>ND3122:DontHardCodeTlsSslProtocolVersions</Id>
warnif count > 0
// Third-party members are part of the code model only when the application uses them.
// The enum value assigned is not visible in IL, but pinning any version is discouraged:
// the OS negotiates the best protocol when the setting is left to SystemDefault.
let protocolPinningMembers = ThirdParty.Methods.Where(m =>
(m.SimpleName == "set_SecurityProtocol" && m.ParentType.FullName == "System.Net.ServicePointManager") ||
(m.SimpleName == "set_SslProtocols" && m.ParentType.FullNameEqualsAny("System.Net.Http.HttpClientHandler", "System.Net.Http.WebRequestHandler", "Microsoft.AspNetCore.Server.Kestrel.Https.HttpsConnectionAdapterOptions")) ||
(m.SimpleName == "set_EnabledSslProtocols" && m.ParentType.FullNameEqualsAny("System.Net.Security.SslClientAuthenticationOptions", "System.Net.Security.SslServerAuthenticationOptions")) ||
// SslStream.AuthenticateAsClient(host, certs, SslProtocols, checkRevocation) and its Server / Async siblings
(m.ParentType.FullName == "System.Net.Security.SslStream" && m.SimpleName.StartsWith("Authenticate") && m.Name.Contains("SslProtocols")))
.ToHashSetEx()
where protocolPinningMembers.Any()
from m in Application.Methods.UsingAny(protocolPinningMembers)
let protocolPinningMembersUsed = m.MethodsCalled.Intersect(protocolPinningMembers).ToArray()
select new {
m,
protocolPinningMembersUsed,
Debt = 15.ToMinutes().ToDebt(),
Severity = Severity.Medium
}
//<Expl>
// The *{0}* pins the TLS/SSL protocol version(s) through *{1}*.
// A hard-coded version list freezes the application on today's protocols:
// it keeps deprecated ones enabled after they are broken and blocks newer ones.
//</Expl>
//<Desc>
// Matches methods setting *ServicePointManager.SecurityProtocol*,
// *HttpClientHandler.SslProtocols*, *SslClientAuthenticationOptions.EnabledSslProtocols*,
// Kestrel *HttpsConnectionAdapterOptions.SslProtocols*, or calling an
// *SslStream.Authenticate...* overload with an explicit *SslProtocols*.
// Microsoft's guidance since .NET Framework 4.7 / .NET Core is to leave
// the protocol at *SystemDefault* / *None* so that the operating system
// picks the strongest version available and drops SSL 3.0, TLS 1.0 and
// TLS 1.1 as they are retired:
// https://learn.microsoft.com/dotnet/framework/network-programming/tls
//
// This is CWE-326 *Inadequate Encryption Strength* when the pinned list
// includes an obsolete version.
//
// **Flagged Code**
// ```csharp
// public HttpClient CreateClient() {
// // flagged: freezes the application on TLS 1.2 and blocks TLS 1.3
// ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
// var handler = new HttpClientHandler { SslProtocols = SslProtocols.Tls12 }; // flagged
// return new HttpClient(handler);
// }
// ```
//
// **Fixed Code**
// ```csharp
// public HttpClient CreateClient() {
// // Target .NET Framework 4.7+ or .NET Core and leave the protocol to the OS
// // (SystemDefault): the strongest version is negotiated, retired ones drop out.
// return new HttpClient(new HttpClientHandler());
// }
// ```
//</Desc>
//<HowToFix>
// Remove the assignment (or set *SecurityProtocolType.SystemDefault* /
// *SslProtocols.None*) and target .NET Framework 4.7+ or .NET Core, so
// the OS controls protocol selection. If a peer requires a specific
// version, isolate that configuration and suppress the issue with a
// justification.
//</HowToFix>
Open in the interactive Rules Explorer · All default rules
Security: all 39 items
- Software Composition Analysis (SCA) ND3120
- Transitive Software Composition Analysis (SCA) ND3121
- Don't hard-code secrets in constants ND3114
- Review credentials built from hard-coded values ND3115
- Don't use insecure deserializers ND3110
- Don't use weak hash algorithms (MD5, SHA1) ND3109
- Don't use DES/3DES/RC2 weak cipher algorithms ND3102
- Don't use weak password-based key derivation ND3123
- Don't use the ECB encryption mode ND3132
- Don't disable certificate validation ND3103
- Don't hard-code TLS/SSL protocol versions ND3122
- Review commands vulnerable to SQL injection ND3107
- Review data adapters vulnerable to SQL injection ND3108
- Review raw SQL built from composed strings ND3128
- Review LDAP filters composed from strings ND3137
- Don't enable external XML entity resolution (XXE) ND3111
- Review processes started with a composed arguments string ND3124
- Review web endpoints building file paths from their parameters ND3129
- Review custom archive extraction (Zip Slip) ND3135
- Review assemblies and types loaded from runtime-provided names ND3125
- Review web endpoints without [Authorize] nor [AllowAnonymous] ND3118
- Review state-changing endpoints opened to anonymous callers ND3130
- Review state-changing MVC actions without anti-forgery validation ND3119
- Review HTML-encoding bypasses ND3133
- Review explicitly disabled request validation ND3134
- Review redirects to a URL that is not validated as local ND3126
- Review request-influenced outbound HTTP calls (SSRF) ND3136
- Review insecure ASP.NET Core CORS policies and unguarded developer exception page ND3116
- Review cookies created without HttpOnly and Secure flags ND3117
- Review regular expressions without a match timeout (ReDoS) ND3112
- Review secrets compared with non-constant-time equality ND3113
- Review secrets passed to logging methods ND3127
- Review security operations that log nothing ND3131
- Don't use System.Random for security purposes ND3101
- Don't use CoSetProxyBlanket and CoInitializeSecurity ND3100
- Review publicly visible event handlers ND3104
- Pointers should not be publicly visible ND3105
- Seal methods that satisfy non-public interfaces ND3106
- Restrict sensitive APIs to reviewed components ND3138