A Guideline 2.5.2 rejection reads as if Apple thinks your app is downloading code to rewrite itself, and for most apps the fix is narrower than it sounds. The rule is about self-contained bundles, and the line it draws sits between updating what your app already does and downloading new functionality. Here is where that line is and how to get back across it.
Short answer
Guideline 2.5.2 requires your app to be self-contained, so it may not download, install, or execute code that introduces or changes its features. Per Apple's App Review Guidelines, over-the-air updates of JavaScript and assets are allowed when they revise existing functionality without changing the app's primary purpose, which is why frameworks like CodePush and EAS Update can pass. What trips the rule is dynamic code that adds features, such as fetching and running remote scripts or an eval of server-supplied code. The fix is to remove that path, keep any OTA inside JS and assets, and resubmit a new build.
What you should know
- The rule is self-containment: your bundle may not download or execute code that adds or changes features.
- OTA of JS and assets is allowed: updating existing functionality through CodePush or EAS Update is within the rules.
- Primary purpose is the test: downloaded interpreted code must not change what the app is for.
- An eval of remote code is the classic trigger: fetching and running server-supplied code adds functionality and violates 2.5.2.
- The fix needs a new build: removing a dynamic-code path is a code change, so you rebuild and resubmit.
What does Guideline 2.5.2 actually prohibit?
It prohibits an app from downloading, installing, or executing code that introduces or changes its features or functionality, including other apps. Apple's wording is that apps should be self-contained in their bundles and may not read or write outside the designated container area, nor download or run code that changes features. The one narrow exception is for educational apps that teach coding, where the downloaded code is viewable and editable by the user and used for nothing else. For a normal app the safe reading is simple: the functionality you ship is the functionality App Review approved, and you cannot add to it from a server afterward.
Is an over-the-air update like CodePush or EAS Update allowed?
Yes, within limits. The Apple Developer Program License Agreement, in section 3.3.2, allows interpreted code to be downloaded as long as it does not change the app's primary purpose by adding features inconsistent with its advertised purpose, does not create a store for other code, and does not bypass signing, the sandbox, or other security. Updating your JavaScript bundle and assets through EAS Update or CodePush fits inside that allowance, because you are revising existing behavior rather than shipping a new app. The limit is real: an OTA channel that turns a flashlight app into a chat app, or that downloads a native binary, is the kind of change that crosses the line.
Why would an AI-built app trip 2.5.2?
Because generated code sometimes reaches for the quickest dynamic pattern. An AI-built app might fetch a snippet of JavaScript from your backend and run it with eval to render a screen, load a remote script into a WebView that adds a feature, or include a hot-update library wired to pull arbitrary bundles. Each of these is a server-to-app code path that App Review treats as downloading executable code. The reviewer does not need to watch it run; a static reference to a remote-bundle download method in the binary can be enough to cite 2.5.2. That is the gap between code that works in a demo and code that survives review.
How do you fix a Guideline 2.5.2 rejection?
Find the dynamic-code path, remove it, and ship a self-contained build. The order that works:
- Identify what Apple flagged: read the rejection, then search your code for eval, Function constructors, remote-bundle download calls, and WebView loads of remote scripts.
- Decide whether each is needed: a remote eval that renders UI should become real in-bundle code, and a misconfigured hot-update import you do not use should be removed entirely.
- Keep legitimate OTA inside the rules: if you use CodePush or EAS Update, confirm it only updates JS and assets for your existing features, not new functionality.
- Rebuild and resubmit: removing a code path changes the binary, so you upload a new build and it re-enters review.
- Reply with specifics: tell the reviewer which dynamic path you removed, so the same concern is easy to clear.
What to watch out for
Remote configuration is fine; remote code is not. Toggling a feature that already exists in the approved binary with a server flag is allowed, because you are not adding functionality, only switching what is already there. The trap is a library that can download and execute new code even if you never trigger it, because the capability itself can draw the citation. AI-built apps are prone to this when a generated integration loads remote scripts. A pre-submission scan such as PTKD.com (https://ptkd.com) reads the compiled APK, AAB, or IPA for dynamic-code patterns like remote-bundle loading and eval against OWASP MASVS, so you find a hidden code path before App Review does. The honest limit is that no scan can read intent, so pair it with a look at every place your app talks to your own backend.
What to take away
- Guideline 2.5.2 requires a self-contained app; you cannot download or execute code that adds or changes features after approval.
- Over-the-air updates of JavaScript and assets through CodePush or EAS Update are allowed, as long as they do not change the app's primary purpose.
- The common trigger is dynamic code that adds functionality, such as an eval of remote scripts, which is a code change and needs a new build to remove.
- Scan the binary for hidden dynamic-code paths with a pre-submission scan such as PTKD.com before resubmitting, so a leftover eval or remote-bundle call does not draw the same rejection twice.



