import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;

public class UnsafeHostnameVerification {

	private static final boolean DISABLE_VERIFICATION = true;

	/**
	 * Test the implementation of trusting all hostnames as an anonymous class
	 */
	public void testTrustAllHostnameOfAnonymousClass() {
		HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
			@Override
			public boolean verify(String hostname, SSLSession session) {
				return true; // BAD, always returns true
			}
		});
	}

	/**
	 * Test the implementation of trusting all hostnames as a lambda.
	 */
	public void testTrustAllHostnameLambda() {
		HttpsURLConnection.setDefaultHostnameVerifier((name, s) -> true); // BAD, always returns true
	}

	/**
	 * Test an all-trusting hostname verifier that is guarded by a flag
	 */
	public void testGuardedByFlagTrustAllHostname() {
		if (DISABLE_VERIFICATION) {
			HttpsURLConnection.setDefaultHostnameVerifier(ALLOW_ALL_HOSTNAME_VERIFIER); // GOOD: The all-trusting
																						// hostname verifier is guarded
																						// by a feature flag
		}
	}

	public void testGuardedByFlagAccrossCalls() {
		if (DISABLE_VERIFICATION) {
			functionThatActuallyDisablesVerification();
		}
	}

	private void functionThatActuallyDisablesVerification() {
		HttpsURLConnection.setDefaultHostnameVerifier((name, s) -> true); // GOOD [but detected as BAD], because we only
																			// check guards inside a function
		// and not accross function calls. This is considerer GOOD because the call to
		// `functionThatActuallyDisablesVerification` is guarded by a feature flag in
		// `testGuardedByFlagAccrossCalls`.
		// Although this is not ideal as another function could directly call
		// `functionThatActuallyDisablesVerification` WITHOUT checking the feature flag.
	}

	public void testTrustAllHostnameDependingOnDerivedValue() {
		String enabled = System.getProperty("disableHostnameVerification");
		if (Boolean.parseBoolean(enabled)) {
			HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true);  // GOOD [but detected as BAD].
			                                                                   // This is GOOD, because it depends on a feature
			                                                                   // flag, but this is not detected by the query.
		}
	}

	/**
	 * Test the implementation of trusting all hostnames as a variable
	 */
	public void testTrustAllHostnameOfVariable() {
		HostnameVerifier verifier = new HostnameVerifier() {
			@Override
			public boolean verify(String hostname, SSLSession session) {
				return true; // BAD, always returns true
			}
		};
		HttpsURLConnection.setDefaultHostnameVerifier(verifier);
	}

	public static final HostnameVerifier ALLOW_ALL_HOSTNAME_VERIFIER = new HostnameVerifier() {
		@Override
		public boolean verify(String hostname, SSLSession session) {
			return true; // BAD, always returns true
		}
	};
}


@@ -105,16 +105,55 @@
 Session;
+%0Aimport java.security.cert.Certificate;
 %0A%0Apublic
@@ -2168,31 +2168,41 @@
 GOOD
- %5Bbut detected as BAD%5D.
+, because it depends on a feature
 %0A%09%09%09
@@ -2275,175 +2275,735 @@
  // 
-This is GOOD, because it depends on a feature%0A%09%09%09                                                                   // flag, but this is not detected by the query.%0A%09%09%7D
+flag.%0A%09%09%7D%0A%09%7D%0A%0A%09public void testTrustAllHostnameWithExceptions() %7B%0A%09%09HostnameVerifier verifier = new HostnameVerifier() %7B%0A%09%09%09@Override%0A%09%09%09public boolean verify(String hostname, SSLSession session) %7B%0A%09%09%09%09verify(hostname, session.getPeerCertificates());%0A%09%09%09%09return true; // GOOD %5Bbut detected as BAD%5D. The verification of the certificate is done in another method and%0A%09%09%09%09    // in the case of a mismatch, an %60Exception%60 is thrown so the %60return true%60 statement never gets executed.%0A%09%09%09%7D%0A%0A%09%09%09// Black-box method that properly verifies the certificate but throws an %60Exception%60 in the case of a mismatch.%0A%09%09%09private void verify(String hostname, Certificate%5B%5D certs)%7B%7D%0A%09%09%7D;%0A%09%09HttpsURLConnection.setDefaultHostnameVerifier(verifier);
 %0A%09%7D%0A

Update test