Skip to content
BuildThenTestedSee packages
CriticalMobile

Secrets in the mobile app bundle

Anyone who downloads the app from the store can unzip it and read the key, then run up your bill or read your database as an administrator. Risks specific to an app installed on a phone. Check it yourself with the steps below; our test adds what a script and a second account can find.

What it looks like

# .env
EXPO_PUBLIC_OPENAI_API_KEY=sk-...
EXPO_PUBLIC_SUPABASE_SERVICE_ROLE_KEY=eyJ...

// app/lib/ai.ts
const client = new OpenAI({ apiKey: process.env.EXPO_PUBLIC_OPENAI_API_KEY });
Expo environment variables with the EXPO_PUBLIC_ prefix, which the build tool copies as plain text into the app that ships to the store.

What happens

Anyone who downloads the app from the store can unzip it and read the key, then run up your bill or read your database as an administrator.

Where it shows up

Descriptive, not a verdict: builders and stacks whose defaults make this reachable, or that a public incident names. Each hub states the tool's own security features.

Seen in public

Escape analysed more than 5,600 publicly deployed apps built with AI app builders and found more than 2,000 vulnerabilities, over 400 exposed secrets and 175 instances of exposed personal data.

  • more than 5,600 Apps analysed
  • more than 2,000 Vulnerabilities found
  • 400+ Exposed secrets
  • 175 Exposed PII instances

Oct 2025 · Escape · all sources

Check it yourself

Uses your builder's dashboard and your browser. No tools to install.

  1. Open the project's .env files and app.json or app.config.js; list every variable whose name starts with EXPO_PUBLIC_ or that sits under extra.
  2. For each one, ask whether the value would matter if a stranger had it: anything starting sk_live_, sk-, or a service-role or admin key is a secret and does not belong there.
  3. If you have a built .apk or .ipa, rename it to .zip, extract it and search the extracted files for the key value or for sk_live.
  4. A bad result is a paid API key or a server-side key in an EXPO_PUBLIC_ variable, or any secret string found inside the extracted app.

What we check

We pull the JavaScript bundle and native resources out of the build you ship to the stores, run secret detection across them, and test whether each key found is live and what it can do. The report names each key, its scope and the file it sat in.

Fix direction

Move calls that need a secret behind a small server function (Supabase Edge Function, Firebase Function or a serverless route) and keep only public, restricted keys in the app. Expo's EAS environment variables offer a secret visibility level for build-time values, and Expo's own documentation says anything included in client-side code should be considered public.

Mechanism documented in: Expo Docs: Environment variables in Expo (EXPO_PUBLIC_ prefix) (verified 2026-09-21); Expo Docs: Environment variables in EAS (visibility levels) (verified 2026-09-21).

Related patterns

  • Third-party API key in the JavaScript bundleSecrets and keys

    Anyone who views the page source can take the key and run up charges, send messages or pull data on your account until the key is revoked.

    High
  • Service-role key shipped in the browser bundleSecrets and keys

    Anyone who opens the app can copy the key from the downloaded JavaScript and read, change or delete every row in every table.

    Critical
  • LLM API key exposed to the clientAI features

    Anyone who views the page source can copy the key and run their own workloads on your account until the bill or the provider stops them.

    Critical
  • NEXT_PUBLIC_ prefix on a secretSecrets and keys

    The build writes the secret's value into public JavaScript, so anyone who loads the site can read it, and a redeploy with the same variable name republishes it.

    Critical

Questions

are expo public environment variables safe for api keys

No. Expo's documentation states that EXPO_PUBLIC_ variables will be visible in plain text in your compiled application, and tells you not to store sensitive information such as private keys in them. Use them only for values that are fine to publish, such as a public project URL or an anon key protected by data rules.

can someone extract api keys from my react native app

Yes. An app from the store is an archive that anyone can unzip, and the JavaScript bundle inside is searchable text. Keys that were inlined at build time appear there as written. Move any key that costs money or grants access behind a server function and call that instead.

how do i use secrets in an expo app without exposing them

Keep the secret on a server: an edge function or serverless route that holds the key and does the work, with the app calling it as a signed-in user. For build-time values, EAS environment variables have a secret visibility level that is not readable outside the EAS servers. Nothing that ends up in the app itself can be kept from the person holding the phone.

Back to the catalogue, or run the self-check for your stack.