RORK LABJP
DEADLINE — From August 31, 2026, Google Play requires target API level 36 (Android 16) or higher for both new apps and updates to existing ones. Thirteen days leftEXTENSION — If you cannot make the date, the deadline extension form in Play Console buys you until November 1. The extension is not automatic, so the request itself has to land before August 31TARGET SDK — Even for Expo and React Native apps produced by builders like Rork, the targetSdkVersion is yours to verify. A template pinned to an older SDK will not meet the requirement on its ownPOLICY — The spam and minimum functionality policy has been tightened around high-quality features and content experience, which puts thin, mass-produced apps squarely in scopePRIVACY — You are expected to explain in detail what data is collected, how it is used, and whether it is shared, including analytics SDKs and advertising identifiers a builder wires in for youRORK — Where the original Rork emits React Native and Expo, Rork Max generates SwiftUI. There is a free tier to start with, and paid plans begin at $25 per monthDEADLINE — From August 31, 2026, Google Play requires target API level 36 (Android 16) or higher for both new apps and updates to existing ones. Thirteen days leftEXTENSION — If you cannot make the date, the deadline extension form in Play Console buys you until November 1. The extension is not automatic, so the request itself has to land before August 31TARGET SDK — Even for Expo and React Native apps produced by builders like Rork, the targetSdkVersion is yours to verify. A template pinned to an older SDK will not meet the requirement on its ownPOLICY — The spam and minimum functionality policy has been tightened around high-quality features and content experience, which puts thin, mass-produced apps squarely in scopePRIVACY — You are expected to explain in detail what data is collected, how it is used, and whether it is shared, including analytics SDKs and advertising identifiers a builder wires in for youRORK — Where the original Rork emits React Native and Expo, Rork Max generates SwiftUI. There is a free tier to start with, and paid plans begin at $25 per month
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.

Rork535Security8Expo171Environment VariablesOperations6

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 $10 for lifetime access
View Membership →

Related Articles

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.
Dev Tools2026-08-14
Your lockfile's dev/prod split won't tell you which licenses your app must credit
A record of classifying every dependency in a production project to decide what belongs on an app's license screen, and where the copyleft findings and the actual shipped artifact turned out to disagree.
📚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 →