A Guideline 2.5.2 rejection lands in App Store Connect with a short message, no specifics about the offending code path, and a developer wondering whether their entire architecture just got blocked. The answer is usually narrower than the panic suggests: Apple is looking at one specific kind of code download, not at every network call your app makes.
Short answer
Guideline 2.5.2 stops apps from downloading or executing code that changes the app's features after review. The common triggers are vibe coding apps, dynamic UI engines that fetch behavior from a server, and WebViews loading remote scripts with privileged capability. The exception is narrow: educational apps where users write and read their own code in plain view.
What you should know
- Guideline 2.5.2 protects the review process, not your users. Apple's concern is apps that change their behavior after approval without going back through review.
- JavaScript and Lua are not banned outright. What is blocked is downloaded code that runs as logic and changes features, not local scripts shipped inside your bundle.
- The educational exception is narrow. Code must be teaching-oriented and fully visible and editable to the user. Hidden execution does not qualify.
- Vibe coding apps are the current enforcement focus. Apple removed Anything in March 2026 and previously blocked Replit and Vibecode updates over the same guideline.
- Web content inside a WebView is generally fine. Remote scripts that interact with native bridges to invoke device features are the risk.
What does Guideline 2.5.2 actually prohibit?
The guideline text reads: "Apps should be self-contained in their bundles, and may not read or write data outside the designated container area, nor may they download, install, or execute code which introduces or changes features or functionality of the app, including other apps." That is the canonical wording from Apple's App Review Guidelines.
Three behaviors fall inside that ban. First, downloading binary code (executables, dynamic libraries, signed scripts) that runs as part of your app. Second, downloading interpreted code (JavaScript, Lua, Python, embedded scripts) that is then executed by a runtime inside your binary. Third, fetching configuration that drives native behavior in a way that crosses from data into logic. The line between data and logic is where most rejections live.
The educational exception sits in one sentence and is easy to misread. The code in question has to be the thing the user is learning to write or read, not a vendor's library quietly updating itself in the background. Reviewers apply the exception narrowly.
What code patterns most often trigger a 2.5.2 rejection?
Reviewers look at a small set of patterns. A pre-submission self-audit against this list catches most cases before they happen.
| Pattern | Example | Risk level |
|---|---|---|
| Remote JavaScript executed by a native bridge | JS downloaded from your server and evaluated by JSContext with access to native APIs | High |
| Dynamic UI engine driven by remote schema | Server returns a layout DSL that maps to native components and includes inline behavior | Medium to High |
| Over-the-air feature flags that toggle compiled paths | A flag switches between two feature paths already in the binary | Low |
| Lua or Python interpreter loading new user scripts | Game engine downloading new level logic, scripting app evaluating downloaded snippets | High |
| WKWebView loading remote HTML and JS for content | Rendering a marketing page or in-app browser content | Low |
A common confusion: WebViews running arbitrary JavaScript do not automatically violate 2.5.2. The line is what that JavaScript can do. JavaScript in a WKWebView rendering web content the way a normal browser would is fine. JavaScript evaluated in a JSContext, or passed through a bridge that invokes native modules and changes app behavior, is the problem.
The 2017 change to the guideline added a sentence narrowing the educational exception, and MacStories noted at the time that the framing made the rule less about the language used and more about what the downloaded code can reach.
Why are vibe coding apps hit hardest right now?
Vibe coding apps, where a user types a prompt and the app builds a working mini app on the fly, run directly into 2.5.2 because the generated app behavior comes from a server and runs inside the parent app. As reported by 9to5Mac in March 2026, Apple removed the Anything app from the App Store after rejecting a submission that tried to redirect generated previews to a web browser. Replit and Vibecode have also seen updates blocked on similar grounds.
Apple's position is consistent with the older policy. The company is not against AI-generated code as a concept; the company is against AI-generated code that runs inside the binary with native capability and without going through review. The acceptable shape today is rendering generated apps in a sandboxed web preview, or sending users to a separately submitted app that contains the result.
What does the educational exception actually cover?
The exception was added so apps like Swift Playgrounds and learn-to-code platforms could exist. To qualify, the downloaded code has to be the subject of the lesson, not a hidden library. Source code must be completely viewable and editable by the user. The code cannot be used for purposes beyond learning, which rules out scripts that perform real work for the user.
As Saagar Jha analyzed after iSH (a Linux shell on iOS) was rejected, reviewers in practice apply the exception narrowly. iSH was eventually approved, but only after a long negotiation about whether a shell counts as educational. If your app is not explicitly a teaching tool, do not plan to rely on this exception as a shield.
How do you respond to a 2.5.2 rejection?
A response in App Store Connect should be specific and short, not defensive. Identify the exact code path the reviewer likely flagged. Explain in plain language what your app does and does not download. If you ship interpreted code that was misread as a runtime executor, point to the file location and show that it is bundled, not fetched.
If the app genuinely fetches logic from a server, the options are three. Bundle the logic into the binary and ship it with the next release. Move execution to a server you control with results returned as data. Open a Resolution Center thread to discuss the educational exception, if it honestly applies. The first option closes the rejection fastest. The third option works only when the app's whole purpose is teaching code.
For builders who want an external automated read of their build before resubmitting, PTKD.com (https://ptkd.com) is one of the platforms focused on pre-submission scanning aligned with OWASP MASVS for no-code and vibe-coded apps. A scan will not predict reviewer behavior, but it will flag the obvious 2.5.2 risk patterns: embedded JS interpreters with bridges to native code, JSContext usage paired with network calls, and Lua or Python runtimes inside the bundle.
What to watch out for
Three myths show up in 2.5.2 panic threads on Reddit. The first is that any JavaScript at all triggers the rejection. False; the issue is execution context and capability, not the language itself. The second is that turning off a feature flag fixes a 2.5.2 rejection. Usually false; reviewers look at what the app can do, not what it does on first launch. The third is that an educational disclaimer in the App Store description protects the app. The educational exception is about behavior, not marketing copy.
The harder edge case is over-the-air update tooling like CodePush, Expo Updates, and EAS Updates. Apple's stated position is that these are acceptable when updates do not change app behavior beyond bug fixes and UI tweaks. The unwritten line is what counts as a "behavior change," and that line moves based on how the SDK is interpreted by a given reviewer. Treat OTA update tooling as observed-but-unpredictable: documented as allowed, applied with discretion.
Key takeaways
- A 2.5.2 rejection is about downloaded code that runs as logic and changes app features, not about every dynamic network call.
- The most common 2026 triggers are vibe coding apps, dynamic UI engines with inline behavior, and JavaScript bridges to native APIs.
- The educational exception is narrow and requires fully visible, user-editable code with no other use.
- A clean response in App Store Connect identifies the suspected code path and either bundles the logic into the binary or moves execution server-side.
- Some teams outsource pre-submission scanning to platforms like PTKD.com (https://ptkd.com) to catch 2.5.2-shaped risks (embedded JS engines, scripting runtimes, native bridges) before they reach a reviewer.



