◉RORK LABJP
●GPT6.1 — GPT-6.1 Sol joined the Rork model menu (Sep 29). It is the latest entry on the changelog●10/12 — 7 days left until React Native 0.88.x is due. Expo SDK 58 stable is only described as early October●NEW — Multiseat Purchases Are Already On: Decide Whether to Keep Them Before October 22●SDK 58 — A fix PR (#50998) for npm install failing in new projects is under review. No stable date has been given yet●SONNET — Claude Sonnet 5.5 is now in Rork (Sep 28). It is described as over 30% faster than Sonnet 5●iOS 27 — From April 2027, App Store uploads require the iOS 27 SDK. There is time to update your build environment calmly●GPT6.1 — GPT-6.1 Sol joined the Rork model menu (Sep 29). It is the latest entry on the changelog●10/12 — 7 days left until React Native 0.88.x is due. Expo SDK 58 stable is only described as early October●NEW — Multiseat Purchases Are Already On: Decide Whether to Keep Them Before October 22●SDK 58 — A fix PR (#50998) for npm install failing in new projects is under review. No stable date has been given yet●SONNET — Claude Sonnet 5.5 is now in Rork (Sep 28). It is described as over 30% faster than Sonnet 5●iOS 27 — From April 2027, App Store uploads require the iOS 27 SDK. There is time to update your build environment calmly
Articles/Dev Tools
⬡ Dev Tools/2026-08-16Advanced

Find the Code That Trips App Store 2.5.2 Before You Submit

If a remote value can change what your app does, Guideline 2.5.2 may apply. Here is where the line actually sits, plus a script that surfaces the risky paths in your repo before submission.

App Store89App Review3Expo212React Native238Remote Config10

✦ Premium Article

There is one moment that always makes me pause: adding a new key to remote config.

Changing a color from the server is fine. Swapping out an entire screen from the server is a different animal. The wallpaper apps I run ship their catalog and their copy from a backend, and the wider that remote surface gets, the smoother operations become — right up until review.

In March 2026, Apple blocked App Store updates for Replit and Vibecode. The cited basis was Guideline 2.5.2, and the reported issue was that both let users generate code and then run it inside the reviewed app (Apple Blocks Updates for AI Vibe Coding Apps in App Store).

If you ship apps built with Rork, that story is closer to home than it looks. Nothing stops you from letting an AI write your code. What can stop you is leaving a path where code gets executed inside the app — and that path can slip in without anyone deciding to add it.

What follows is a way to surface those paths mechanically, with the script I actually ran and what running it taught me about its own blind spots.

2.5.2 is about whether behavior changes, not where code comes from

Start with the text. Guideline 2.5.2 says apps should not "download, install, or execute code which introduces or changes features or functionality of the app, including other apps" (App Review Guidelines).

The easy misread is the subject. What is prohibited is not downloading code. What is prohibited is introducing or changing functionality by doing so.

You can confirm that reading by working backward from the carve-outs. JavaScript running inside WebKit is fine under this rule. Educational apps may, under conditions, download code for students to run. Neither exception would make sense if the rule were a blanket ban on remote code.

I had this wrong for a while myself. I designed as if anything fetched from a server was suspect. The real line is narrower and more specific.

What arrives from the serverWhat happens in the appThrough the 2.5.2 lens
Wallpaper catalog JSONThe list shows different itemsData swap. Behavior is unchanged
A Remote Config thresholdAn existing branch is taken differentlyInside the reviewed feature set
An EAS Update JS bundleThe implementation is replaced wholesaleInterpreted-layer update. An accepted practice
An expression string passed to evalNew logic comes into existence at runtimeIntroduces functionality
A dynamic import from a remote URLCode nobody reviewed runsIntroduces functionality

Rows three and four are where the rule becomes legible. An EAS Update replaces your entire JS bundle. By volume, that dwarfs handing one line of text to eval. Yet the first is an established workflow and the second is the thing that gets apps pulled.

The boundary is not drawn around delivery. It is drawn around whether the app can exceed the feature set that was reviewed. OTA updates are treated as replacing the implementation of an app that keeps the same purpose and the same features. eval leaves an opening for logic that nobody had seen at review time. It is a question of scope, not of bytes.

Once you hold it that way, decisions get fast. Adding something new, ask yourself: am I delivering, or am I generating? The answer usually arrives on the spot.

Six implementations that cross the line

Here is the scan target. At indie scale, these are the six that realistically show up. The first three should be gone before you submit; the last three are fine to keep if you can explain what feeds them.

  1. eval(...) — runs a string as code
  2. new Function(...) — treated the same as eval. Hand-rolled expression evaluators love this one
  3. import("https://...") — pulls a remote module at runtime
  4. injectedJavaScript — JS injected into a WebView. A constant is fine; a string from your server is not
  5. source={{ html: ... }} — a path for rendering arbitrary HTML
  6. A map that picks a screen from a remote value, like components[remote.screen]

Items four through six are not on the "delete it" list because they are legitimate, widespread patterns. Rendering help content in a WebView is normal. Reordering tabs from remote config is normal. The problem only appears when the value flowing in comes from outside and its contents are not fixed ahead of time.

So treat these six as a list of places to trace an input back to its source, not a list of things to remove on sight.

✦

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
✦You can tell which parts of your own codebase could fall under 2.5.2, reading it straight from the source before you submit
✦You can draw the line in your own design between what a remote value may change (data, settings) and what it must not (the behavior itself)
✦You avoid the scramble of ripping out features after a rejection, so your launch date survives a period when review times are long
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-06-12
Building a Developer Debug Menu Into Your Rork App — Verify Ads, Purchases, and Remote Config Before Release
A production-safe developer debug menu for Rork apps — switch environments, force test ads, simulate entitlements, and override Remote Config, with working TypeScript code and the pitfalls I hit running six apps.
⬡ Dev Tools2026-09-10
I Added a Dim Screen Button, and iPhones Stayed Dark After the App Was Closed
In expo-brightness, setBrightnessAsync applies only to the current activity on Android, but changes the device brightness itself on iOS. Here is why the cleanup burden falls on one platform only, and a hook that restores brightness through AppState.
⬡ Dev Tools2026-09-04
EAS secret visibility does not keep a value out of your app — deciding prefix and visibility separately
The EXPO_PUBLIC_ prefix decides what ships inside your app; EAS visibility decides who can read it. Why stacking them blanks a value on OTA updates, and how to check your build.
📚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