RORK LABJP
DEADLINE — From August 31, every new app and update on Google Play must target Android 16 (API level 36). Seven days to goEXTENSION — If you qualify, you can request an extension through November 1 using a form in Play Console, but the request itself has to be filed before the deadlineMAX — Rork Max generates native Swift rather than React Native and compiles on a cloud Mac fleet, covering iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and iMessageCOMPANION — The Rork Companion app lets you test on a real iPhone without a paid Apple Developer account, so design, build, and test can all happen in a browserDEVTOOLS — React Native DevTools in Expo SDK 57 can emulate light and dark mode, letting you check both appearances without touching device settingsIOS27 — iOS 27 ships next month. Beta 6 landed on August 17, and RCS Universal Profile 3.0 support means you can finally reply to a specific message received from AndroidDEADLINE — From August 31, every new app and update on Google Play must target Android 16 (API level 36). Seven days to goEXTENSION — If you qualify, you can request an extension through November 1 using a form in Play Console, but the request itself has to be filed before the deadlineMAX — Rork Max generates native Swift rather than React Native and compiles on a cloud Mac fleet, covering iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and iMessageCOMPANION — The Rork Companion app lets you test on a real iPhone without a paid Apple Developer account, so design, build, and test can all happen in a browserDEVTOOLS — React Native DevTools in Expo SDK 57 can emulate light and dark mode, letting you check both appearances without touching device settingsIOS27 — iOS 27 ships next month. Beta 6 landed on August 17, and RCS Universal Profile 3.0 support means you can finally reply to a specific message received from Android
Articles/Dev Tools
Dev Tools/2026-07-10Advanced

Every Key You Ship Is Public: Secret Boundaries and Rotation for Rork-Generated Apps

Unzip your own .ipa, run strings, and your environment variables are right there in plain text. Here is how I sort keys into three tiers, move the dangerous ones behind an edge proxy, and keep a rotation runbook that assumes leakage.

Rork543Security8Expo181Environment VariablesOperations7

Premium Article

I unzipped one of my own .ipa files late one evening and piped the binary through strings.

There it was: the value I had named EXPO_PUBLIC_ANALYTICS_KEY, sitting in the output as plain text. No obfuscation, no encoding. From build artifact to extracted key took about ten seconds.

I knew this intellectually. Seeing my own binary read my own key back to me was a different experience entirely.

Running six apps solo means the key count reaches double digits fast. Ads, subscriptions, analytics, crash reporting, translation APIs. When you let a generator write the scaffolding, all of that initialization code appears at remarkable speed. The one decision it cannot make for you is where each key belongs.

What follows is how I put that decision into words, then applied it across all six apps.

A key on the client is not encrypted. It is published.

Start from the premise. The moment an app bundle lands on a user's device, it is readable.

In Expo, keys live as strings inside the JavaScript bundle. In Swift, they live in the binary's string table. Obfuscation raises the cost of extraction; it does not create a boundary.

The fastest way to internalize this is to check your own artifact.

# iOS: an .ipa is a zip. Unpack it and run strings on the binary.
unzip -q MyApp.ipa -d /tmp/ipa
strings /tmp/ipa/Payload/MyApp.app/MyApp | grep -iE 'key|secret|token' | head -20
 
# Expo: grep the JS bundle directly
grep -oE 'EXPO_PUBLIC_[A-Z_]+"[^"]*"' /tmp/ipa/Payload/MyApp.app/main.jsbundle | head -20
 
# Android: the same trick works on an apk
unzip -q app-release.apk -d /tmp/apk
strings /tmp/apk/classes.dex | grep -iE 'AIza|sk_live|pk_live' | head

Three commands tell you exactly what your app publishes. I have made this a ritual before any new app ships.

Everything those commands surface is public information. You do not hide it. You design so that publishing it costs you nothing.

Sort every key into one of three tiers

Thinking in terms of "secret or not" leads to paralysis. Three tiers make the placement decision fall out automatically.

Tier Nature Examples Where it lives Cost if exposed
Tier 1: public identifiers Never secret to begin with AdMob app and unit IDs, RevenueCat public SDK key, Sentry DSN Hardcoded in the client is fine Effectively none; abuse is blocked at other layers
Tier 2: restricted public keys Meant to be visible, but only with constraints Firebase web API key, Maps API key, write-only analytics keys Client is acceptable, provided the issuer restricts bundle ID, referrer, and scope Metered-billing abuse, but only when restrictions are missing
Tier 3: real secrets Whoever holds it can act as your server OpenAI or Gemini API keys, Stripe secret key, RevenueCat secret API key, Supabase service_role key Server or edge function only. Never the client. Direct charges on your card; full read and write on your data

When a key resists classification, ask one question: could a stranger holding this key spend my money or read all of my users' rows? If yes, it is tier 3, and prefixing it with EXPO_PUBLIC_ loses the game before it starts.

The most commonly missed part of tier 2 is the restriction itself. A Google Cloud key without an application restriction (Android package name or iOS bundle ID) and an API restriction (an explicit list of endpoints it may call) is a tier-3 key wearing a tier-2 costume.

If you are still fighting with variables that simply refuse to load, why Rork environment variables fail to resolve covers that ground first.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
A three-command audit that extracts secrets from your own shipped binary, and the three-tier classification it forces
A working edge proxy that hides tier-3 keys and caps the financial blast radius with rate limits and body caps
A rotation runbook built on the assumption that keys leak, plus a CI gate that stops the same mistake twice
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $15 for lifetime access
View Membership →

Related Articles

Dev Tools2026-08-22
Every bulk replace exited zero. The damage was in the lines I did not delete
Run a bulk replace over generated code and the breakage lands on the neighbouring lines, not the matched ones. Here is what broke in a live project, and a dependency-free guard that checks the invariants a replace must preserve.
Dev Tools2026-06-27
Before a Free Preview Walks Out via Screenshot: Detecting Screenshots and Screen Recording in Rork/Expo
How to protect paid preview images from screenshots and screen recording in a Rork/Expo app: the limits of expo-screen-capture, native isCaptured monitoring, and an iOS/Android-aware blur design.
Dev Tools2026-06-16
Keeping Expo Push Tokens from Slipping Through the Cracks in Production
After adding re-engagement push to a Rork-generated Expo app, the delivered count came in well below the active install count. The cause was missed token updates and stale tokens left to pile up. Here is the lifecycle I settled on, with code: registration, refresh, server storage, and pruning.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →