Enable server certificate validation on this SSL/TLS connection. Open
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
- Read upRead up
- Exclude checks
Validation of X.509 certificates is essential to create secure SSL/TLS sessions not vulnerable to man-in-the-middle attacks.
The certificate chain validation includes these steps:
- The certificate is issued by its parent Certificate Authority or the root CA trusted by the system.
- Each CA is allowed to issue certificates.
- Each certificate in the chain is not expired.
This rule raises an issue when an implementation of X509TrustManager is not controlling the validity of the certificate (ie: no exception is
raised). Empty implementations of the X509TrustManager
interface are often created to disable certificate validation. The correct
solution is to provide an appropriate trust store.
Noncompliant Code Example
class TrustAllManager implements X509TrustManager { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { // Noncompliant, nothing means trust any client } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { // Noncompliant, this method never throws exception, it means trust any server LOG.log(Level.SEVERE, ERROR_MESSAGE); } @Override public X509Certificate[] getAcceptedIssuers() { return null; } }
See
- OWASP Top 10 2017 Category A6 - Security Misconfiguration
- MITRE, CWE-295 - Improper Certificate Validation
- CERT, MSC61-J. - Do not use insecure or weak cryptographic algorithms
Change this code to use a stronger protocol. Open
sslcontext = SSLContext.getInstance("SSL");
- Read upRead up
- Exclude checks
This rule raises an issue when an insecure TLS protocol version is used (ie: a protocol different from "TLSv1.2", "TLSv1.3", "DTLSv1.2" or "DTLSv1.3").
Noncompliant Code Example
javax.net.ssl.SSLContext
library:
context = SSLContext.getInstance("TLSv1.1"); // Noncompliant
okhttp library:
ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) .tlsVersions(TlsVersion.TLS_1_1) // Noncompliant .build();
Compliant Solution
javax.net.ssl.SSLContext
library:
context = SSLContext.getInstance("TLSv1.2"); // Compliant
okhttp library:
ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) .tlsVersions(TlsVersion.TLS_1_2) // Compliant .build();
See
- OWASP Top 10 2017 Category A3 - Sensitive Data Exposure
- OWASP Top 10 2017 Category A6 - Security Misconfiguration
- MITRE, CWE-327 - Inadequate Encryption Strength
- MITRE, CWE-326 - Use of a Broken or Risky Cryptographic Algorithm
- SANS Top 25 - Porous Defenses
- Diagnosing TLS, SSL, and HTTPS
- SSL and TLS Deployment Best Practices - Use secure protocols
Enable server hostname verification on this SSL/TLS connection. Open
return true;
- Read upRead up
- Exclude checks
To establish a SSL/TLS connection not vulnerable to man-in-the-middle attacks, it's essential to make sure the server presents the right certificate.
The certificate's hostname-specific data should match the server hostname.
It's not recommended to re-invent the wheel by implementing custom hostname verification.
TLS/SSL libraries provide built-in hostname verification functions that should be used.
This rule raises an issue when:
-
HostnameVerifier.verify()
method always returnstrue
- a JavaMail's
javax.mail.Session
is created with aProperties
object having nomail.smtp.ssl.checkserveridentity
ormail.smtps.ssl.checkserveridentity
not configured totrue
- a Apache Common Emails's
org.apache.commons.mail.SimpleEmail
is used withsetSSLOnConnect(true)
orsetStartTLSEnabled(true)
orsetStartTLSRequired(true)
without a call tosetSSLCheckServerIdentity(true)
Noncompliant Code Example
URL url = new URL("https://example.org/"); HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection(); urlConnection.setHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String requestedHost, SSLSession remoteServerSession) { return true; // Noncompliant } }); InputStream in = urlConnection.getInputStream();
SimpleEmail example:
Email email = new SimpleEmail(); email.setSmtpPort(465); email.setAuthenticator(new DefaultAuthenticator(username, password)); email.setSSLOnConnect(true); // Noncompliant; setSSLCheckServerIdentity(true) should also be called before sending the email email.send();
JavaMail's example:
Properties props = new Properties(); props.put("mail.smtp.host", "smtp.gmail.com"); props.put("mail.smtp.socketFactory.port", "465"); props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); // Noncompliant; Session is created without having "mail.smtp.ssl.checkserveridentity" set to true props.put("mail.smtp.auth", "true"); props.put("mail.smtp.port", "465"); Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("username@gmail.com", "password"); } });
Compliant Solution
URL url = new URL("https://example.org/"); HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection(); // Compliant; Use the default HostnameVerifier InputStream in = urlConnection.getInputStream();
SimpleEmail example:
Email email = new SimpleEmail(); email.setSmtpPort(465); email.setAuthenticator(new DefaultAuthenticator(username, password)); email.setSSLOnConnect(true); email.setSSLCheckServerIdentity(true); // Compliant email.send();
JavaMail's example:
Properties props = new Properties(); props.put("mail.smtp.host", "smtp.gmail.com"); props.put("mail.smtp.socketFactory.port", "465"); props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.port", "465"); props.put("mail.smtp.ssl.checkserveridentity", true); // Compliant Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("username@gmail.com", "password"); } });
See
- OWASP Top 10 2017 Category A6 - Security Misconfiguration
- MITRE, CWE-295 - Improper Certificate Validation
- Derived from FindSecBugs rule WEAK_HOSTNAME_VERIFIER
Enable server certificate validation on this SSL/TLS connection. Open
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
- Read upRead up
- Exclude checks
Validation of X.509 certificates is essential to create secure SSL/TLS sessions not vulnerable to man-in-the-middle attacks.
The certificate chain validation includes these steps:
- The certificate is issued by its parent Certificate Authority or the root CA trusted by the system.
- Each CA is allowed to issue certificates.
- Each certificate in the chain is not expired.
This rule raises an issue when an implementation of X509TrustManager is not controlling the validity of the certificate (ie: no exception is
raised). Empty implementations of the X509TrustManager
interface are often created to disable certificate validation. The correct
solution is to provide an appropriate trust store.
Noncompliant Code Example
class TrustAllManager implements X509TrustManager { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { // Noncompliant, nothing means trust any client } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { // Noncompliant, this method never throws exception, it means trust any server LOG.log(Level.SEVERE, ERROR_MESSAGE); } @Override public X509Certificate[] getAcceptedIssuers() { return null; } }
See
- OWASP Top 10 2017 Category A6 - Security Misconfiguration
- MITRE, CWE-295 - Improper Certificate Validation
- CERT, MSC61-J. - Do not use insecure or weak cryptographic algorithms
Make this anonymous inner class a lambda (sonar.java.source not set. Assuming 8 or greater.) Open
new HostnameVerifier(){
- Read upRead up
- Exclude checks
Before Java 8, the only way to partially support closures in Java was by using anonymous inner classes. But the syntax of anonymous classes may seem unwieldy and unclear.
With Java 8, most uses of anonymous inner classes should be replaced by lambdas to highly increase the readability of the source code.
Note that this rule is automatically disabled when the project's sonar.java.source
is lower than 8
.
Noncompliant Code Example
myCollection.stream().map(new Mapper<String,String>() { public String map(String input) { return new StringBuilder(input).reverse().toString(); } }); Predicate<String> isEmpty = new Predicate<String> { boolean test(String myString) { return myString.isEmpty(); } }
Compliant Solution
myCollection.stream().map(input -> new StringBuilder(input).reverse().toString()); Predicate<String> isEmpty = myString -> myString.isEmpty();
Return an empty array instead of null. Open
return null;
- Read upRead up
- Exclude checks
Returning null
instead of an actual array or collection forces callers of the method to explicitly test for nullity, making them more
complex and less readable.
Moreover, in many cases, null
is used as a synonym for empty.
Noncompliant Code Example
public static List<Result> getResults() { return null; // Noncompliant } public static Result[] getResults() { return null; // Noncompliant } public static void main(String[] args) { Result[] results = getResults(); if (results != null) { // Nullity test required to prevent NPE for (Result result: results) { /* ... */ } } }
Compliant Solution
public static List<Result> getResults() { return Collections.emptyList(); // Compliant } public static Result[] getResults() { return new Result[0]; } public static void main(String[] args) { for (Result result: getResults()) { /* ... */ } }
See
- CERT, MSC19-C. - For functions that return an array, prefer returning an empty array over a null value
- CERT, MET55-J. - Return an empty array or collection instead of a null value for methods that return an array or collection
Identical blocks of code found in 2 locations. Consider refactoring. Open
if (headers != null) {
Iterator<Entry<String, String>> headersIterator = headers.entrySet().iterator();
while (headersIterator.hasNext()) {
Entry<String, String> header = headersIterator.next();
connnection.setRequestProperty(header.getKey(), header.getValue());
- Read upRead up
Duplicated Code
Duplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:
Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
When you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).
Tuning
This issue has a mass of 46.
We set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.
The threshold configuration represents the minimum mass a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.
If the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.
See codeclimate-duplication
's documentation for more information about tuning the mass threshold in your .codeclimate.yml
.
Refactorings
- Extract Method
- Extract Class
- Form Template Method
- Introduce Null Object
- Pull Up Method
- Pull Up Field
- Substitute Algorithm
Further Reading
- Don't Repeat Yourself on the C2 Wiki
- Duplicated Code on SourceMaking
- Refactoring: Improving the Design of Existing Code by Martin Fowler. Duplicated Code, p76