2

I updated the version code and version name of app but i got warning message from google play

Your app(s) are using an unsafe implementation of the HostnameVerifier interface. You can find more information about how resolve the issue in this Google Help Center article.

thanks in advance

Thomas Fritsch
  • 9,639
  • 33
  • 37
  • 49
gaurav gupta
  • 513
  • 1
  • 6
  • 13
  • 1
    Possible duplicate of [Google Play Security Alert - Your app is using an unsafe implementation of the HostnameVerifier](https://stackoverflow.com/questions/40928435/google-play-security-alert-your-app-is-using-an-unsafe-implementation-of-the-h) – Maciej Jureczko Oct 08 '17 at 11:55

2 Answers2

2

Had plenty of versions we assumed were right in this Flutter project and had been rejected over and over again but finally, we figured out. 

Pubspec.yaml  - previous version.

flutter_html: ^0.11.1
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  http: ^0.12.0+2
  provider: ^4.1.3
  logger: ^0.7.0+2
  shared_preferences: ^0.5.4+6
  json_annotation: ^3.0.0
  flutter_dotenv: ^2.1.0
  flutter_swiper: ^1.1.6
  package_info: ^0.4.0+3
  get_version: ^0.2.0+1
  uuid: ^2.0.4
  flappy_translator: ^1.2.2
  flutter_circular_chart: ^0.1.0
  percent_indicator: "^2.1.1"
  intl: ^0.16.0
  bezier_chart: ^1.0.15
  charts_flutter: ^0.8.1
  fl_chart: ^0.6.0
  flutter_native_timezone: ^1.0.4
  url_launcher: ^5.7.8
  permission_handler: ^5.0.1+1
  onesignal_flutter: 2.6.1
  flutter_braintree: 1.1.0
  after_layout: ^1.0.7+2
  flutter_svg: ^0.19.0
  custom_switch_button: 0.5.0
  wc_flutter_share: ^0.2.2
  esys_flutter_share: ^1.0.2
  just_audio: ^0.4.4
  cached_network_image: 2.2.0+1
  sqflite: ^1.3.1
  cupertino_icons: ^0.1.2
  in_app_purchase: 0.3.4+5

Hostname verification

    HttpsURLConnection.setDefaultHostnameVerifier { hostname, arg1 ->      
val herokuPattern = “PROJECTNAME-(dev|stg|prd)\\.herokuapp.com”.toRegex()      
val awsPattern = “PROJECTNAME-(dev|stg|prd)\\.s3\\..*\\.amazonaws.com”.toRegex()
              herokuPattern.containsMatchIn(hostname) 
    ||      awsPattern.containsMatchIn(hostname) 
    ||        hostname.equals(“onesignal.com”, ignoreCase = true) 
    ||        hostname.equals(“api.braintreegateway.com”, ignoreCase = true) 
    ||        hostname.equals(“payments.braintree-api.com”, ignoreCase = true) 
    ||        hostname.equals(“api.sandbox.braintreegateway.com”, ignoreCase = true) 
    ||        hostname.equals(“payments.sandbox.braintree-api.com”, ignoreCase = true)    }

After the first try we got this message as you do:

HostnameVerifierYour app(s) are using an unsafe implementation of the HostnameVerifier interface. You can find more information about how resolve the issue in this Google Help Center article.

Then we turned to the ‘Google Development/Developer support’ with the question what should we do as there was lack of information about the problem. After a week we received a message and had a better understanding not how can we find the solution but at least where to find it.

Vulnerable implementation of HostnameVerifier:

  • Lf/a/a/a/a/l/e$a;
  • Lf/a/a/a/a/l/f$a;
  • To properly handle hostname verification, you'll need to change the verify method in your custom HostnameVerifier interface to return false whenever the hostname of the server does not meet your expectations. You may refer to the Alerts page of your Play Console for additional guidance.

Exposed Google Cloud Platform (GCP) API key(s). 

  • com.onesignal.h2->dLocations of exposed GCP API keys in your app can be found in the Play Console notification for your app. You may refer to this Help Center page to fix the leaked credentials vulnerability issue.

OneSignal related info was pretty clear, after a short search we found a similar comment that recommends setting the version number (from 2.6.1) to onesignal_flutter: 2.6.2. OneSignal problem solved.

Genuinely, there were two weeks desperate times when we could not find anything for the  Vulnerable implementation problem, nor with the ‘Developer Support’ advice:

“Although I’m happy to answer any questions about managing your apps on the Google Play Store, our team isn’t trained to provide technical support for app development questions. For help developing Android apps, I recommend using our Android Developers site. The site has technical documentation, the Android SDK, and tips for distributing your apps.” - GooglePlay Developer Support.

Eventually, we had to look after vulnerability issues regarding the plugins we used and found a Braintree issue that suggests setting the version number to flutter_braintree: 1.1.0+1

After these two versions-number upgrade (Onesignal, Braintree) got no more message about the HostameVerifier issue, all seem well. 

Pubspec.yaml

flutter_html: ^0.11.1
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  http: ^0.12.0+2
  provider: ^4.1.3
  logger: ^0.7.0+2
  shared_preferences: ^0.5.4+6
  json_annotation: ^3.0.0
  flutter_dotenv: ^2.1.0
  flutter_swiper: ^1.1.6
  package_info: ^0.4.0+3
  path_provider: 1.6.24
  get_version: ^0.2.0+1
  uuid: ^2.0.4
  flappy_translator: ^1.2.2
  flutter_circular_chart: ^0.1.0
  percent_indicator: "^2.1.1"
  intl: ^0.16.0
  bezier_chart: ^1.0.15
  charts_flutter: ^0.8.1
  fl_chart: ^0.6.0
  flutter_native_timezone: ^1.0.4
  url_launcher: ^5.7.8
  permission_handler: ^5.0.1+1
  onesignal_flutter: 2.6.2
  flutter_braintree: 1.1.0+1
  after_layout: ^1.0.7+2
  flutter_svg: ^0.19.0
  custom_switch_button: 0.5.0
  wc_flutter_share: ^0.2.2
  esys_flutter_share: ^1.0.2
  just_audio: ^0.5.7
  cached_network_image: 2.2.0+1
  sqflite: ^1.3.1
  cupertino_icons: ^0.1.2
  in_app_purchase: 0.3.4+5
  • Thsnk you for valuable information. Google should clearly provide some insight or guide if they are rejecting your app :/ – NightFury Jan 23 '21 at 20:40
1

Surely you have a code similar to this

 HostnameVerifier hostnameVerifier = new HostnameVerifier() {
     @Override
     public boolean verify(String hostname, SSLSession session) {
        HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
        return true;
     }
};

Or:

HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier(){ 
                public boolean verify(String hostname, SSLSession session) { 
                        return true; 
                }}); 

Replace by:

 HostnameVerifier hostnameVerifier = new HostnameVerifier() {
     @Override
     public boolean verify(String hostname, SSLSession session) {
        HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
        if(myHostNameToVerify==hostname || myOtherHostNameToVerify == hostname) {

            return true;
        } else {
            return false;
        }
     }
};

Or:

HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier(){ 
                public boolean verify(String hostname, SSLSession session) { 
                        if(myHostNameToVerify==hostname || 
                           myOtherHostNameToVerify == hostname) {

                             return true;
                        } else {
                             return false;
                        }
                }}); 

If you use a SSL verifier, I recommend to add code similar to this:

 @Override
 public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {
// the main thing is to show dialog informing user
// that SSL cert is invalid and prompt him to continue without 
// protection: handler.proceed();
// or cancel: handler.cancel();
String message;
switch(error.getPrimaryError()) {
    case SslError.SSL_DATE_INVALID:
        message = ResHelper.getString(R.string.ssl_cert_error_date_invalid);
        break;
    case SslError.SSL_EXPIRED:
        message = ResHelper.getString(R.string.ssl_cert_error_expired);
        break;
    case SslError.SSL_IDMISMATCH:
        message = ResHelper.getString(R.string.ssl_cert_error_idmismatch);
        break;
    case SslError.SSL_INVALID:
        message = ResHelper.getString(R.string.ssl_cert_error_invalid);
        break;
    case SslError.SSL_NOTYETVALID:
        message = ResHelper.getString(R.string.ssl_cert_error_not_yet_valid);
        break;
    case SslError.SSL_UNTRUSTED:
        message = ResHelper.getString(R.string.ssl_cert_error_untrusted);
        break;
    default:
        message = ResHelper.getString(R.string.ssl_cert_error_cert_invalid);
}
mSSLConnectionDialog = new MaterialDialog.Builder(getParentActivity())
        .title(R.string.ssl_cert_error_title)
        .content(message)
        .positiveText(R.string.continue_button)
        .negativeText(R.string.cancel_button)
        .titleColorRes(R.color.black)
        .positiveColorRes(R.color.main_red)
        .contentColorRes(R.color.comment_grey)
        .backgroundColorRes(R.color.sides_menu_gray)
        .onPositive(new MaterialDialog.SingleButtonCallback() {
            @Override
            public void onClick(MaterialDialog materialDialog, DialogAction dialogAction) {
                mSSLConnectionDialog.dismiss();
                handler.proceed();
            }
        })
        .onNegative(new MaterialDialog.SingleButtonCallback() {
            @Override
            public void onClick(MaterialDialog materialDialog, DialogAction dialogAction) {
                handler.cancel();
            }
        })
        .build();
mSSLConnectionDialog.show(); 

Google from mid-2016 and early 2017 require a more secure code.

Suaro
  • 312
  • 2
  • 11
  • hello sir HostnameVerifier hostnameVerifier = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier(); return true; } }; I have not added this code but i am getting msg from google unsafe implementation of hostnameverifier – gaurav gupta Oct 08 '17 at 18:24
  • Do you use any type of SSL / TLS verification? – Suaro Oct 08 '17 at 19:55
  • no, this code is written by someone but he has gone so, this app is assigned to me – gaurav gupta Oct 09 '17 at 06:18
  • It's so strange, the error that you application has, is produced by insecure implementation of HostnameVerifier. Make sure of your code or some dependency library not use an implementation of HostnameVerifier, X509Certificate, setDefaultHostnameVerifier, SSLSocketFactory, X509HostnameVerifier or any SSL / TLS that uses SSL / TLS. In any case, check out the following Android documentation https://support.google.com/faqs/answer/7188426 – Suaro Oct 09 '17 at 19:37
  • I checked ,paytm sdk is creating problem , now i have updated sdk – gaurav gupta Oct 10 '17 at 05:22
  • Any fix to this, I am facing the same issue. – Kanwarpreet Singh Dec 14 '20 at 10:38