.env file bundled into the Flutter app as an asset
ID |
dart.config.bundled_dotenv_asset |
Severity |
critical |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Config |
Language |
Dart |
Description
A .env (or secrets.json / credentials.yml / api_keys.properties / service_account.json) file is listed under flutter > assets: in pubspec.yaml. Anything in assets: is bundled into the shipped APK / IPA and trivially extractable.
Rationale
Flutter’s assets: block packages the listed files into the
application bundle so they can be read at runtime via
rootBundle.loadString(…). The packaging happens AS-IS — the
files are not encrypted, not obfuscated, and not protected by the
Dart obfuscator (which only operates on Dart code).
Anyone with the shipped APK / IPA can:
-
Unzip the APK:
unzip app.apk→assets/flutter_assets/→ every asset including.envreads as plaintext. -
Mount the IPA: same principle, same plaintext access.
-
Pull the binary off a rooted / jailbroken device or a forensic image — same result.
A .env file in assets: is the moral equivalent of committing
it to a public GitHub repo. The same applies to any
secrets.json, service_account.json, or credentials.yml —
these filename patterns very specifically signal credentials,
and bundling them in the app means "the credentials ship to
every user".
Remediation
Move secrets out of assets:. Three reasonable alternatives:
-
Build-time injection:
flutter build apk --dart-define=API_KEY=… --dart-define-from-file=secrets.envand read withString.fromEnvironment('API_KEY').--dart-define-from-filereads a JSON / env file at build time and embeds the keys as compile-time constants (still in the snapshot, but no longer a bundled asset — and they can be different per build flavor / per CI runner). -
Runtime fetch: download the user-scoped secret from an authenticated backend after sign-in; store in
flutter_secure_storage. -
Per-user derived: derive at runtime from a user passphrase via Argon2id / PBKDF2; nothing of value is shipped in the bundle.
# Vulnerable
flutter:
assets:
- .env
- assets/secrets.json
- config/service_account.json
# Fixed (assets contains only non-secret resources)
flutter:
assets:
- assets/images/logo.png
- assets/i18n/en.json
References
-
OWASP Top 10 2025 - A02 : Security Misconfiguration.
-
OWASP Top 10 2025 - A07 : Authentication Failures.
-
CWE-798 — Use of Hard-coded Credentials (covers the secret inside the asset)
-
Talsec — OWASP Mobile Top 10 for Flutter M1 — Mastering credential security in Flutter (M1 — Improper Credential Usage)
-
Cossack Labs — Flutter application security considerations — Documents that the Dart obfuscator does not protect bundled assets