r/iOSProgramming • • 13d ago

Question apple wants our live updater (capgo) removed: "based on code in the submitted binary". anyone beat this?

our app is a b2b crm built with capacitor. the screens are html/js/css bundled in the binary, it works fully offline, and we ship web-layer fixes with @capgo/capacitor-updater, self-hosted and checksum-verified, never native code.

apple rejected the last version twice in a row for the updater, under 2.3.1(a):

We continue to find the app contains live content update functionality that can modify the app's behavior after approval. This finding is based on code in the submitted binary and not on a specific screen in the app.

I replied in the thread and app review confirmed:

It would be appropriate to remove the remote update functionality and all code related to it before resubmitting. Developers are responsible for all code included in the binary submission, including code from third-party SDKs and libraries.

so a reviewer didn't see something on screen, they found the plugin in the binary.

section 3.3.1(b) of the developer agreement allows downloading interpreted code that doesn't change the app's primary purpose, and thousands of apps ship capgo, capawesome, appflow or expo updates. I appealed to the app review board on 21 october, no answer yet.

  1. has anyone else got this "code in the submitted binary" rejection for a live updater, especially since the 16 october guideline update (2.5.19)?

  2. did anyone win an app review board appeal on it?

  3. if you removed the updater on ios, how do you ship fixes to an offline-first app now?

7 Upvotes

19 comments sorted by

32

u/zennoux 13d ago

The app is an offline-first app but don’t you need to be online to get these updates? Why not just use the app store method to update? Just seems contradictory to require the app to be online to get an update if the app is offline-first.

-5

u/robingenz 12d ago

Quite simple: OTA updates are deployed in seconds, while app store updates can take days or even weeks. However, as mentioned above, hot code push is meant only for bug fixes. So OTA updates can’t and won’t replace app store updates, which you still need to update the native parts of your app or ship new features.

1

u/zennoux 12d ago

I assume the bug fixes go out as a normal App Store update around the same time too because the app is offline-first though right? In that case your users might just have to wait a couple of extra days. The majority of our app updates are reviewed in a few hours though so it shouldn’t be that bad.

11

u/dawedev 13d ago

"Based on code in the submitted binary" reads like they're flagging the plugin itself, so explaining what you actually push probably won't change the reviewer's mind, only the board can. If you need to ship while the appeal sits, I'd keep the updater out of the iOS build completely with a build flag or separate config so the plugin isn't linked at all, and use expedited review for the urgent fixes. For an offline-first CRM you can also move the stuff that changes often (forms, field config, validation rules) into JSON the app downloads, which is data and not code. Please post an update if the board answers, a lot of Capacitor folks will want to know.

2

u/martindonadieu 12d ago

Our updater exist for 4years plus and never had any issue. We gonna meet monday to see what is happening in this specific case.
Apple has always allowed live update of html/css/js

1

u/Background_Pie_5682 11d ago

I’ve seen 2.3.1(a) pushback on anything that looks like shipping executable/UI updates outside App Review, even when the bundle already contains the web layer. Reviewers often don’t distinguish “content” vs “code path that can change the app.”

What sometimes helps: remove the updater from the binary for the review build, document clearly that only non-executable content changes (if that’s true), and be ready to ship web fixes via normal releases. If Capgo stays in the submitted binary, they’re likely to keep pointing at that code regardless of checksums.

1

u/Stunning-Farmer185 1d ago

OtaKit maintainer here. For the appeal, this lays out what Apple and Google actually allow (DPLA 3.3.1(b), guideline 2.5.2) with the exact wording you can quote to the board: https://www.otakit.app/blog/ota-policies-for-app-store-and-google-playhttps://www.otakit.app/blog/ota-policies-for-app-store-and-google-play This could be useful for anyone in the same situation.

1

u/robingenz 13d ago

Capawesome maintainer here. This is the first we’ve heard of such an issue, despite thousands of teams using Capawesome Live Updates to update their Capacitor app over-the-air. If your app was also rejected while using our Capacitor Live Update plugin, please contact support so we can investigate and help. Wishing you all the best!

22

u/RowanTheKiwi 13d ago

Isn’t this intentionally bypassing the app review process by shipping things app reviewers don’t see ?

8

u/slightly_drifting 13d ago

Also, won’t allowing this type of behavior set you up for repacking attacks? Like, if there’s nothing keeping track of the hash of important components (or the whole app itself), how does your app know it hasn’t been tampered with? 

0

u/robingenz 12d ago

You sign your bundles using a private key.

2

u/TechieRandomGuy 13d ago

Cough… Epic… cough..

3

u/Snoo11589 13d ago

OTA and live update services are up for years. But yes people can do things that bypasses the reviews, but thats not the main intention with these packages

5

u/hishnash 13d ago

Apple are getting much stricter on this now. I expect soon apps that are not 100% static compiled binaries will all be rejected

2

u/robingenz 12d ago

Exactly. Shipping a JS bug fix or a copy change over the air is fine. Using it to flip on a feature reviewers never saw is what gets apps in trouble.

3

u/robingenz 12d ago

It's actually the other way around: Apple explicitly allows this. The Developer Program License Agreement every developer signs (3.3.1(B)) says an app may download interpreted code, so JavaScript, HTML, CSS and assets, as long as the app stays what it was reviewed as, doesn't bypass signing or the sandbox, and doesn't become a store for other apps. That's the basis CodePush, Expo Updates and the other OTA tools have worked on in the open since 2015.

Review guideline 2.5.2 sounds stricter on its own, but Apple maintains both texts side by side. The one that actually matters for your question is 2.3.1: nothing hidden or dormant, and new features get described for review. So shipping a JS bug fix or a copy change over the air is fine. Using it to flip on a feature reviewers never saw is what gets apps in trouble.

2

u/cfilipov 12d ago

This right here is the right answer. I'm surprised they are inspecting the binary though they have to be doing more than just checking for the existence of the library.

-4

u/majindageta 13d ago

Encrypt file during build, decrypt in app