Search code examples
androidandroid-webviewandroid-security

How to address "Remediation for JavaScript Interface Injection Vulnerability"?


Google has asked me to address https://support.google.com/faqs/answer/9095419 in my Android app, which basically means not to use the JavaScript injection mechanism for a web page loaded via HTTP.

Not using this mechanism (option 1) doesn't work for me. Setting android:usesCleartextTraffic to false also doesn't work, as the app uses non-HTTPS traffic elsewhere. So that leaves me with "you can ensure that any affected WebViews do not load any URLs with HTTP schemes via loadUrl" - which I'm happy to do, as my app only uses file:/// URLs to load content into the WebView, which should be fine security-wise. But how do I need to code the shouldOverrideUrlLoading method so that Google's checker recognizes that I'm using only file:/// URLs?

Note that the question is different from both Remediation for JavaScript Interface Injection Vulnerability (because I'm clear what is being asked) and In Android, JavaScript Interface Injection Vulnerability (because I'm not using HTTP, but file:/// URLs).

Edit: Adding my shouldOverrideUrlLoading method. (This isn't the entire method, but the salient part of it.)

    @Override
    public boolean shouldOverrideUrlLoading (WebView browser, String url) {
        if (url.startsWith("file:///")) {
            // This is my web site, so do not override; let my WebView load the page
            browser.loadUrl(url);
            return true;
        }

        // Otherwise, the link is not for a page on my site, or is an entirely different kind of URI
        // (like tel:, geo: or mailto:), so launch another Activity that handles URLs
        act.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
        return true;
    }

Solution

  • I have not found a way to use file:// URLs with assets in a way that satisfies Google code checker. While this would solve the issue, I'm still not clear how one might need to code it.

    What I ended up doing -which solves my immediate problem- is to call a JavaScript method via the WebView.evaluateJavascript method. When called from within WebViewClient.onPageFinished the page has finished loading, so all elements are accessible. While not important for my case, this method can also return a value to the Java code. So while it's not a general replacement for a JavascriptInterface, it addresses some of its uses cases.