eduardweb.
Expo & EASIntermediar#security#react-native#devops#expo#eas-build

Cum gestionăm corect secrets în Expo: de la .env local la EAS Build fără scurgeri de date

De Andreea Crăciun, 30 iul. 2026 · 8 vizualizări · 2 like-uri

Postat 30 iul. 2026
javascript
module.exports = ({ config }) => {
  return {
    ...config,
    extra: {
      // Accesibile doar prin Constants.expoConfig.extra la runtime
      apiUrl: process.env.API_URL || 'https://dev.api.domeniu.ro',
      sentryDsn: process.env.SENTRY_DSN,
      eas: {
        projectId: '12345678-abcd-1234-abcd-1234567890ab'
      }
    },
    // Cheile de build folosite de plugin-uri (ex: Sentry, Google Maps)
    hooks: {
      postPublish: [
        {
          file: 'sentry-expo/upload-sourcemaps',
          config: {
            organization: 'company-org',
            project: 'mobile-app',
            authToken: process.env.SENTRY_AUTH_TOKEN // Luat din EAS Secrets
          }
        }
      ]
    }
  };
};

Am văzut prea multe aplicații Expo unde chei private de API sau jetoane de webhook ajung împachetate direct în bundle-ul de JavaScript. Acum câteva luni, la un proiect cu peste 12k utilizatori activi, un junior a pus un token de SendGrid într-un .env încărcat direct în app. Pe scurt, am consumat cota de e-mailuri pe o lună în doar 4 ore pentru că botii au extras cheia din aplicația decompilată.

Nu e un caz izolat. În ecosistemul React Native / Expo, confuzia dintre ce e accesibil la runtime pe telefon și ce e doar la build-time este uriașă.

Diferența critică: EXPO_PUBLIC_ vs Build Environment

Expo are convenția asta automată: orice variabilă din .env care începe cu EXPO_PUBLIC_ va fi injectată direct în codul tău client de către Babel. Dacă scrii EXPO_PUBLIC_API_URL, o poți accesa în cod prin process.env.EXPO_PUBLIC_API_URL.

Problema apare când oamenii pun EXPO_PUBLIC_STRIPE_SECRET_KEY. Oricine descarcă APK-ul sau IPA-ul tău poate rula strings index.android.bundle | grep STRIPE și îți fură cheia în 30 de secunde. REGULĂ DE AUR: ce e cu EXPO_PUBLIC_ este public de facto. Nu pune niciodată chei private acolo.

Cum funcționează fișierele .env local

Local, Expo CLI știe să citească .env, .env.development, .env.production sau .env.local în funcție de modul în care pornești bundler-ul. Dacă pornești cu npx expo start, se va încărca .env.development prin default.

Trade-off-ul? Fișierele astea sunt excelente pe mașina ta de dev, dar NU trebuie să ajungă în Git. Le pui direct în .gitignore. Dacă le pui în Git, le-ai compromis. Dar dacă le pui în .gitignore, ce se întâmplă când dai build pe serverele Expo (EAS Build)?

Intrarea în scenă: EAS Secrets

Când rulezi eas build --profile production, codul tău este trimis pe o mașină virtuală în cloud-ul celor de la Expo. Deoarece fișierul .env.production este în .gitignore, mașina de build nu îl are. Dacă aplicația ta depinde de variabile la build-time (de exemplu un token de Sentry sau o cheie de acces la un registru privat de npm), build-ul va eșua.

Aici intervin EAS Secrets. Acestea sunt variabile stocate securizat pe serverele Expo și sunt injectate în mediu doar în timpul procesului de compilare.

Le setezi simplu din terminal: eas secret:create --scope project --name SENTRY_AUTH_TOKEN --value tokenul_tau_secret

Sau prin interfata web din expo.dev dashboard. Când rulezi build-ul, EAS le pune automat în process.env pe VM-ul de build.

Maparea în app.config.js

Pentru a trimite variabilele din mediu către configurația aplicației fără să le expui în JS bundle, folosești app.config.js în loc de staticul app.json. Asta îți permite să le treci în secțiunea extra, pe care o poți citi prin Constants.expoConfig.extra.

Sincer, setup-ul ăsta are un mic minus: devine puțin verbose și uneori e enervant să configurezi separat Secrets pe CLI și .env local. Dar este singura metodă curată prin care te asiguri că datele sensibile nu ajung în pachetul final de JS.

Voi cum gestionați variabilele de mediu când aveți mai mult de 3 medii (dev, staging, uat, prod)? Mă bate gândul să trec totul pe Vault pentru echipă.

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

Doar membrii comunității pot lăsa comentarii.