RORK LABJP
ENGINE — Rork Max is powered by Claude Code and Claude Opus 4.6, generating native Swift apps directlyCORE ML — Rork Max reaches on-device Core ML inference alongside HealthKit, HomeKit, NFC, and App ClipsSEED — Rork raised a $15M seed led by Left Lane Capital in April 2026, joined by Peak XV and a16z SpeedrunM&A — Rork acquired the app builder Paperline and says it will stay acquisitive to bring in engineering talentMARKET — Gartner expects 75% of new applications to be built with low-code or no-code tools by the end of 2026GROWTH — The no-code AI platform market is projected to grow from $4.9B in 2024 to $24.8B by 2029ENGINE — Rork Max is powered by Claude Code and Claude Opus 4.6, generating native Swift apps directlyCORE ML — Rork Max reaches on-device Core ML inference alongside HealthKit, HomeKit, NFC, and App ClipsSEED — Rork raised a $15M seed led by Left Lane Capital in April 2026, joined by Peak XV and a16z SpeedrunM&A — Rork acquired the app builder Paperline and says it will stay acquisitive to bring in engineering talentMARKET — Gartner expects 75% of new applications to be built with low-code or no-code tools by the end of 2026GROWTH — The no-code AI platform market is projected to grow from $4.9B in 2024 to $24.8B by 2029
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.

Rork497Security8Expo138Environment VariablesOperations5

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-07-09
Holding Layer Boundaries in a Rork-Generated Expo App with ESLint and dependency-cruiser
Long-lived Rork-generated Expo apps quietly accumulate screens that import the API client directly. Here is how I froze 214 existing violations as a baseline, eliminated 17 circular dependencies, and made CI reject anything new for 38 extra seconds.
📚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 →