Python grapples with Apple App Store rejections
lwn.net
lwn.net
Try building a Python app with PyInstaller while you have Windows Defender live scanning on, which is the default setting. You won't even be able to compile a binary without Defender preventing you from doing so.
Similarly, try running the binary produced by PyInstaller with Windows Defender on. Defender will say it's malicious and won't run it.
It's a bit dystopian that both major OS platforms go out of their way to prevent you from distributing and running your Python apps.
This is definitely the case and has been my experience, as well.
We live in some dark times when it comes to building and sharing anything as small developers, especially if the things you're building are free.
I stopped updating my open-source Mac apps because I can't justify the cost of jumping over artificial hurdles Apple puts in place that ensure users can't run the apps they want to use. I have other hobbies where spending money actually gives me tangible goods and benefits versus paying an arbitrary yearly tax for the privilege to build stuff that ultimately benefits Apple.
Which is deeply ironic, if you think about it.
This world is just awesome. :)
hah, that's the exact reason I stopped using os x and went full Linux on my old Mac book air about 8 years ago.
The alternative is not signing your binaries and explaining to users that they can run them by right clicking and selecting "Open" from the menu.
> The alternative is not signing your binaries and explaining to users that they can run them by right clicking and selecting "Open" from the menu.
That's what I'm doing now, and it's still an issue, unfortunately. Non-power users are not going to remember the right-click -> Open ritual when they just double-click on everything else.
And the warnings Gatekeeper shows also caused users to think their apps, and even computers, were broken or hacked.
Ironically I've seen tons of actual malware that doesn't even give the slightest warning.
We (sqlitebrowser.org) have recently started using them for signing our Windows builds.
Anyone can just get their malware signed by just throwing some dollars at it.
If you want an engineering OS, use GNU/Linux.
At my job, we build cross-platform software, but we build it on Linux. It runs on Windows, but building it on Windows is torture, so almost all our dev machines are Linux.
Windows is where the users are. Not targeting it is a bad financial decision.
Ideally code signing / validation would be cheaper
https://www.reddit.com/r/learnpython/comments/e99bhe/comment...
If you used the Microsoft-signed or Python Software Foundation-signed Python binaries, maybe it doesn't trip the Defender alarm, same thing if you used older versions of Python or PyInstaller. 3.12.4 only came out on the 6th.
This goes beyond just Python apps. The signing procedures to get past Windows SmartScreen require you to buy certificates and or deeply integrate with the golden path of Windows development. Stray from the Microsoft approved path that and all your users will get a nice scary warning. Part of it is justified by security concerns, but there is a bitter taste of major OSs pushing "the" way to develop.
> Alex Gaynor suggested that the project try a an approach that Keith-Magee had not put forward inspired by Gaynor's experience with the cryptography library. The project often receives complaints that the library refuses to parse a certificate that is technically invalid, but was in wide use. He said that the policy was to accept pull requests that work around those issues ""provided they are small, localized, and generally aren't too awful"". But, he added, these patches should only be accepted on the condition that someone complains to the third party (in this case Apple), and extracts some kind of commitment that they would do something about it. He suggested that the workaround be time-limited, to give users a decent experience ""while also not letting large firms simply externalize their bizarre issues onto OSS projects"".
as a solution to the familiar problem of users wanting OSS to work around bugs in commercial software because OSS maintainers are easier to bully and they know bug reports to Megacorp go straight to a black hole.
Heck, what if I have a malicious web frame inside my app that tries to invoke “itms-services”, similar to this Polyfill.io debacle?
I’m still asking though why, if Apple doesn’t like apps which use this protocol, the sandbox is not intervening; as surely an approved app could have a malicious web view.
However, App Review Guidelines forbid App Store apps from installing other apps, so that scheme gets scanned during review.
Enterprise distribution allows you to deploy applications to corporate managed devices with no App Store review whatsoever. The restrictions are mostly in the business agreement in who you can provide enterprise distribution to (e.g. employees and contractors) and on what your apps can do. The justification is that the enterprise has a relationship with the employee/contractor, is ultimately on the hook for abuses/harms they do via MDM on employee devices.
This is the situation that led to both Facebook and Google having their enterprise accounts banned temporarily a few years ago, as they were each using them as part of a market analysis program - they offered to install VPN software onto consumer devices that monitored web and third-party app usage. Such monitoring is not allowed even for employees per the enterprise developer account agreement.
More seriously, I'm sure they also prevent the privilege to that URI scheme. This is likely part of some ill-thought defense-in-depth approach. Same way they search for the names of private symbols in the exec, even when the linker will outright refuse to give you those. I absolutely detest this pervasiveness of useless layers of security that add almost nothing. But since almost nothing is not nothing, no one can remove any of them. Like cockroach papers, I'm going to call them "cockroach security". Practically everything is infested with those these days.
That sounds like the correct fix, in that it is least likely to get your developer account banned
At this point Apple seems to be using simple substring matches, so if there is any exploit vector the malware authors can circumvent the check using "itms" + "-services" or something more sophisticated like ROT13.
Imagine your app embeds a WebView at myapp.com/terms. It’s your Terms of Service, you show it to everyone when they sign up. Everyone clicks OK.
After it’s on the App Store, you modify your WebView to include `itms-services` for some reason. You’ve just completely bypassed App Store review and gotten that URL handler into your app. The sandbox should stop you - but clearly the review processes don’t consider this possibility and are enforcing it before you publish. Why?
My point is that the scanning for this handler, if Apple doesn’t want to allow it, seems misplaced if they wanted the ban to actually be effective.
There are many ways to get around their restrictions. But doing so will get you banned.
Seems like pretty clear direction to me:
But it has been known for over a decade now that Apple searches binaries for strings. They've never done runtime execution checks which would pick up you actually making such an HTTP call.
Lib/urllib/parse.py contains disallowed string "itms-services" at line 62 column 25
Reason: Apps may not install or launch executable code, such as through the itms-services URI schema.
To get credit for "giving you a clear direction", I'd want them to make available and suggest a fix. In general that could be "if this is a false positive, click to request a human reviewer make an exemption" but ideally monitoring for this kind of issue in the first place (sudden increase in identical rejections) and fixing the broken check.Instead, Apple seem to omit the information on the first line that they likely already get from their internal tool, and not only don't suggest a fix but make the proper fix so unavailable that it's easier to get the language itself changed than a check in their review framework.
> But it has been known for over a decade now that Apple searches binaries for strings. They've never done runtime execution checks which would pick up you actually making such an HTTP call.
It's true that someone with folk knowledge about the way Apple does checks, gleaned about the process by other frustrated users, could likely infer the way in which Apple's test is broken and so eventually deduce the first line from the second line. That's not Apple giving a clear direction - that's developers managing to work around an inscrutable system.
1. Apple received a copy of your source code to do source analysis
2. Apple actually supported running python code as an option for writing iOS apps and wrote source code analysis tools for python for reporting compliance issues
neither of these are true.
From the linked Github issue:
> After lots of 'we can provide you with no further information' I finally submitted an appeal for the rejection which at last resulted in Apple telling me that parse.py and its .pyc were the offending files
It is pretty shitty that the one who sells phones also determines what goes on them.
That way, you can opt into digital serfdom and people like me can opt out.
-
Serf here isn’t pejorative, but descriptive. Apple is behaving like a feudal lord. Down to the claims of protecting the land and arbitrating disputes.
For 99.9% of people, Android and iOS will be virtually identical in terms of freedom, as they will just install apps from the play store and use google-services on the manufacturer-provided (and -bloated) android install that comes with their phone.
That being said, for those who do care, the ability to take control of your phone and run AOSP, an actually FOSS distribution, and only run FOSS apps, or install whatever app you want, is unparalleled on Android vs iOS.
I don't understand why people feel the need to force Apple into a specific strategy when they are not a monopoly. They aren't the only game in town, you don't _need_ an iPhone. Every single person who has an iPhone has chosen to have that device.
Perhaps the reason people don't like the idea that if you want choice you choose the platform that gives you choice, is because Android is a steaming pile of garbage.
I didn't want an iphone. I was forced to get one, because Apple won't allow any web browser on their platform except their web browser. So I can't deliver a working website for iphone users without having a real iphone to develop on. This is an absolutely abusive, anti-competitive and shitty artificial limitation Apple has forced on the world. I'd really rather just tell my users to install Chrome or Firefox and use that instead of being forced to use Safari. This isn't good for developers, and it's not good for their customers whether they know it or not.
As far as the software - Apple owns iOS and licenses it to you for your device.
I bougth it, is not a lease, is not a license to use it, I own the device. I should be able to run whatever I want on it.
Stop spreading missinformation, you are thinking about software.
According to your argument, they __are__ a monopoly. I.e. one on digital serfdom. Because apparently Android is in a different field.
Glad they went with a config option instead.
Apple is saying what test broke, not that other tests aren’t running.
> Some light obfuscation of the magic string appears to avoid the issue.
It is a simple string match causing the failure.
[1] https://discuss.python.org/t/handling-incompatibilities-with...
Put another way: if it was my app, and this string wasn't important to me, I wouldn't want it obfuscated, I'd want it removed.
Guideline 2.5.2 - Performance - Software Requirements
The app installed or launched executable code. Specifically, the app uses
the itms-services URL scheme to install an app.
i.e. the app can't try to trigger an install of another App Store app. The app in question isn't doing that, it's just that the basic check is incompetent for the rule it's supposed to be checking and the reviewer isn't doing any manual checking after that to see if it was a false-positive. So obfuscating the string, if you're genuinely not trying to install other apps, should leave your app just as non-violating as it was before... just not tripping the badly written check.Apple can of course be arbitrary and capricious after that point.
The list is called uses_netloc and is used to help parse the user@host:port part of https, ftp, etc. domains. It’s this list of schemes that includes the forbidden string itms-services, used for Apple’s proprietary iTunes software.
The only code that needs this is urlunsplit and urljoin. If your parsed URL has a netloc then the list isn’t even relevant — if you have a netloc then you are assumed to be in uses_netloc.
This all seems like a much more sensible approach than trying to selectively include or exclude naughty strings from the source code, per some corporation’s passive aggressive demands.
The authority consists of a host with a blank name and blank path (path-abempty).
The issue is a lot of libraries do not make a distinction between a field explicitly being declared blank and being left undeclared (e.g. nil vs ""). Looks like rather than change python's URL library to recognize this distinction, they created an exception list that just hard-codes output behavior.
One can make a case that client software should be robust enough to handle both forms of URL (e.g. itms-service URLs are likely just URI, but the original developers thought all URI should have two forward slashes in them). I can say specifically for "scheme://" calls that such robustness on the recipient side is very rare, because if they understood URI well enough to be robust then they wouldn't have had two extra slashes that they will never use.
¹Also I checked, that standard does actually define an empty host (https://url.spec.whatwg.org/#empty-host) as a distinct concept from a null host.