• Что бы вступить в ряды "Принятый кодер" Вам нужно:
    Написать 10 полезных сообщений или тем и Получить 10 симпатий.
    Для того кто не хочет терять время,может пожертвовать средства для поддержки сервеса, и вступить в ряды VIP на месяц, дополнительная информация в лс.

  • Пользаватели которые будут спамить, уходят в бан без предупреждения. Спам сообщения определяется администрацией и модератором.

  • Гость, Что бы Вы хотели увидеть на нашем Форуме? Изложить свои идеи и пожелания по улучшению форума Вы можете поделиться с нами здесь. ----> Перейдите сюда
  • Все пользователи не прошедшие проверку электронной почты будут заблокированы. Все вопросы с разблокировкой обращайтесь по адресу электронной почте : info@guardianelinks.com . Не пришло сообщение о проверке или о сбросе также сообщите нам.

“Wait… You’re Using .env Files in Flutter for Secrets?” Let’s Talk Before It’s Too Late

Lomanu4 Оффлайн

Lomanu4

Команда форума
Администратор
Регистрация
1 Мар 2015
Сообщения
1,481
Баллы
155
“Bro, did you just ship your API key in plain text inside the APK?”
That’s literally what I asked a friend recently when I cracked open their Flutter app’s .apk.
Spoiler: the .env file was right there, readable like a TODO comment.

And honestly? It’s not just them. I’ve seen this mistake across multiple teams. If you’re using flutter_dotenv without understanding what it does in production, you’re probably exposing secrets too.

So, let’s sit down, dev-to-dev, and go through:

  • Why this happens
  • How to properly pass secrets
  • When to use --dart-define vs. --dart-define-from-file
  • And how to secure your Flutter apps like a pro
? The Mistake: Trusting .env Files in Production


Here’s how it usually goes:

You install flutter_dotenv, create a .env file like this:


API_URL=

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.


API_KEY=super_secret_key

Then in your code:


import 'package:flutter_dotenv/flutter_dotenv.dart';

final apiUrl = dotenv.env['API_URL'];
final apiKey = dotenv.env['API_KEY'];

Looks clean, right?

? But here’s the catch:


flutter:
assets:
- .env

This tells Flutter to bundle .env as a plain asset. That means in your final .apk (which is just a ZIP file), the .env file is just sitting there under /assets/, ready to be opened by anyone who downloads your app.

Don’t believe me? Try it:


unzip build/app/outputs/flutter-apk/app-release.apk
cat assets/.env

Yup. Your secrets are not secreting anymore.

✅ The Solution: Use --dart-define to Pass Secrets Securely


Flutter gives you a better way: --dart-define.

Instead of loading secrets from a file, you inject them at build time and retrieve them from Dart using String.fromEnvironment.

? How to Use It


flutter build apk \
--release \
--obfuscate \
--split-debug-info=./debug_info \
--dart-define=API_URL=

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

\
--dart-define=API_KEY=super_secret_key

And in your Dart code:


const apiUrl = String.fromEnvironment('API_URL');
const apiKey = String.fromEnvironment('API_KEY');

These values are compiled into the app binary — not bundled as assets — making them much harder to extract.

? What If You Have Many Secrets? Use --dart-define-from-file


Now imagine this: you have 5, 10, maybe 15 different keys and toggles — API URLs, feature flags, auth tokens, etc.

Typing all of them into a CLI command gets ugly fast. That’s where --dart-define-from-file comes in.

? Instead of this:


flutter build apk \
--dart-define=API_URL=https://... \
--dart-define=API_KEY=... \
--dart-define=FEATURE_X=true \
--dart-define=CLIENT_ID=...

✅ Do this:

  1. Create a config file:

config.prod.json


{
"API_URL": "

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

",
"API_KEY": "super_secret_key",
"FEATURE_X": "true",
"CLIENT_ID": "xyz-123"
}
  1. Build your app using:

flutter build apk \
--release \
--obfuscate \
--split-debug-info=./debug_info \
--dart-define-from-file=config.prod.json
  1. Access values like before:

const apiUrl = String.fromEnvironment('API_URL');
const apiKey = String.fromEnvironment('API_KEY');
? Use Different Configs for Different Environments


Want to switch between environments?

Make multiple config files:

  • config.dev.json
  • config.staging.json
  • config.prod.json

Then:


flutter build apk --dart-define-from-file=config.dev.json

Easy to manage. Clean. Secure.

? What Not to Do


Here are some real-world mistakes I’ve seen:

❌ Bundling .env in assets
❌ Checking config.prod.json with secrets into Git
❌ Hardcoding secrets in Dart
❌ Skipping code obfuscation

? Bonus: Obfuscation + Code Shrinking = Stronger Defense


Reverse engineering is always a risk, but you can make it much harder:

✅ Enable R8
In android/gradle.properties:


android.enableR8=true

✅ Obfuscate Your Code


flutter build apk \
--release \
--obfuscate \
--split-debug-info=./debug_info \
--dart-define-from-file=config.prod.json

✅ Add ProGuard Rules
Edit android/app/proguard-rules.pro to hide sensitive class names or prevent reflection.

? TL; DR – When to Use What

  • .env + flutter_dotenv — Use Case (Dev only) — Secure for Production? (❌ No) — Scalable? (? Limited)
  • --dart-define — Use Case (Small set of secrets) — Secure for Production? (✅ Yes) — Scalable? (? Medium)
  • --dart-define-from-file — Use Case (Many secrets or different env's) — Secure for Production? (✅ Yes) — Scalable? (✅ Excellent)
? Real App Example


Let’s say your app needs:

  • API_URL
  • API_KEY
  • AUTH_DOMAIN
  • FIREBASE_ID
  • FEATURE_X toggle

Create config.prod.json:


{
"API_URL": "

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

",
"API_KEY": "prod-key",
"AUTH_DOMAIN": "auth.myapp.com",
"FIREBASE_ID": "abcd1234",
"FEATURE_X": "true"
}

Then build your app:


flutter build apk \
--release \
--obfuscate \
--split-debug-info=./debug_info \
--dart-define-from-file=config.prod.json

You now have a secure, production-ready build — without secrets exposed in assets.

? Final Thoughts


If you’ve made it this far, here’s what I want you to remember:

  • .env is not safe for production — don’t ship it.
  • Use --dart-define or --dart-define-from-file instead.
  • Keep secrets out of your frontend when possible.
  • Obfuscate. Shrink. Encrypt. Always.

? Don’t wait for a security audit or a breach to start caring about this.

Your users trust your app — protect that trust.


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

 
Вверх Снизу