Granting file access to WebViews, particularly through the file:// scheme, can expose sensitive local files to malicious scripts.
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.
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.
Exposed data can be exfiltrated to attacker-controlled servers, leading to account compromise, identity theft, and data breaches.
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.
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");
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");