Granting file access to WebViews, particularly through the file:// scheme, can expose sensitive local files to malicious scripts.

Why is this an issue?

WebViews can be configured to allow scripts to access local files through the file:// scheme. When file access settings are enabled, JavaScript running within the WebView can read files from the device’s local file system, including sensitive application data.

Settings such as setAllowFileAccess, setAllowContentAccess, allowFileAccessFromFileURLs, and allowUniversalAccessFromFileURLs control this behavior on Android.

What is the potential impact?

Data exposure

If a malicious script is loaded in a WebView with file access enabled, it can read arbitrary files from the device’s local file system. This includes sensitive application data, user credentials, authentication tokens, and Personally Identifiable Information (PII) stored in local files.

Loss of confidentiality

Exposed data can be exfiltrated to attacker-controlled servers, leading to account compromise, identity theft, and data breaches.

How to fix it

Use WebViewAssetLoader to load local files instead of directly accessing them via file:// URLs. This approach serves assets over a secure https://appassets.androidplatform.net URL, effectively isolating the WebView from the local file system.

The file access settings are disabled by default in modern Android versions. To prevent possible security issues in Build.VERSION_CODES.Q and earlier, it is still recommended to explicitly set those values to false.

Code examples

Noncompliant code example

import android.webkit.WebView;
import android.webkit.WebViewClient;

WebView webView = (WebView) findViewById(R.id.webview);
webView.setWebViewClient(new WebViewClient());
webView.getSettings().setAllowFileAccess(true); // Noncompliant
webView.getSettings().setAllowFileAccessFromFileURLs(true); // Noncompliant
webView.getSettings().setAllowUniversalAccessFromFileURLs(true); // Noncompliant
webView.getSettings().setAllowContentAccess(true); // Noncompliant
webView.loadUrl("file:///android_asset/example.html");

Compliant solution

import android.net.Uri;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import androidx.annotation.RequiresApi;
import androidx.webkit.WebViewAssetLoader;

WebView webView = (WebView) findViewById(R.id.webview);
WebViewAssetLoader assetLoader = new WebViewAssetLoader.Builder()
    .addPathHandler("/assets/", new WebViewAssetLoader.AssetsPathHandler(this))
    .build();

webView.setWebViewClient(new WebViewClient() {
    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
        return assetLoader.shouldInterceptRequest(request.getUrl());
    }

    @SuppressWarnings("deprecation")
    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
        return assetLoader.shouldInterceptRequest(Uri.parse(url));
    }
});

webView.getSettings().setAllowFileAccess(false);
webView.getSettings().setAllowFileAccessFromFileURLs(false);
webView.getSettings().setAllowUniversalAccessFromFileURLs(false);
webView.getSettings().setAllowContentAccess(false);

webView.loadUrl("https://appassets.androidplatform.net/assets/example.html");

Resources

Documentation

Standards