Just got this message for a few of my apps that are live in the app store (and have been for years).

"Your app, extension, and/or linked framework appears to contain code designed explicitly with the capability to change your app’s behavior or functionality after App Review approval, which is not in compliance with section 3.3.2 of the Apple Developer Program License Agreement and App Store Review Guideline 2.5.2. This code, combined with a remote resource, can facilitate significant changes to your app’s behavior compared to when it was initially reviewed for the App Store. While you may not be using this functionality currently, it has the potential to load private frameworks, private methods, and enable future feature changes.

This includes any code which passes arbitrary parameters to dynamic methods such as dlopen(), dlsym(), respondsToSelector:, performSelector:, method_exchangeImplementations(), and running remote scripts in order to change app behavior or call SPI, based on the contents of the downloaded script. Even if the remote resource is not intentionally malicious, it could easily be hijacked via a Man In The Middle (MiTM) attack, which can pose a serious security vulnerability to users of your app.

Apple today has started informing developers that use “hot code push” SDKs that it will soon start rejecting their applications.

[…]

While Apple has yet to publicly comment on the change, the email sent to affected developers seems to imply that services like Rollout.io are the cause.

[…]

It really shouldn’t come as too big of a surprise that Apple is starting to crack down on these type of SDKs. Seeing that they allow changes to be made to an app after App Store review, it’s really a miracle that they have lasted so long in Apple’s generally rather restricted ecosystem. Whether or not this is a good policy on Apple’s part, though, is up for debate.

How can Rollout allow you to push code-level updates to live iOS apps and be fully compliant with Apple’s guidelines? Glad you asked.

[…]

Apple’s guidelines explicitly permit you to push executable code directly to your app, bypassing the App Store, under these two conditions:

The code is run by Apple’s built-in WebKit framework or JavascriptCore

The code does not provide, unlock or enable additional features or functionality

[…]

Rollout isn’t intended to push new features or functionality. It is meant to tweak or fix them, avoiding the minor releases needed to fix bugs, add logging or tracking, update messages, force users to upgrade, etc.

The machine doesn’t know or care what’s public and what’s private. There’s no security boundary between the two. Private APIs do nothing that a third-party developer couldn’t do in their own code, if they knew how to write it. The only way Apple can check for private API usage is to have a big list of all the private APIs in their libraries and scan the app looking for calls to them. This is fundamentally impossible to do with certainty, because there’s an unlimited number of ways to obfuscate such calls.

Functionality that needs to be restricted due to privacy or security concerns has to be implemented in a completely separate process with requests from apps being made over some IPC mechanism. This is the only way to reliably gate access.

Apple’s prohibition against using private APIs is like an “employees only” sign on an unlocked door in a store. It serves a purpose, but that purpose is to help keep well-meaning but clueless customers away from an area where they might get confused, or lost, or hurt. It won’t do anything for your store’s security.

While Apple has not modified its guidelines, it appears that these guidelines are now being interpreted in a more narrow way. We are disappointed that Apple has made this change before we have had an opportunity to address any concerns. We have already reached out to Apple to discuss and are committed to adjusting our offering as needed to remain in compliance under the more narrow interpretation of the guidelines.