Repository navigation
Apple App Store rejecting apps because of "(ITMS-91061) Missing privacy manifest" #132006
Description
I've received a report (beeware/Python-Apple-support#268) that the iOS App Store is now rejecting apps that include a Python framework with the following error:
ITMS-91061: Missing privacy manifest - Your app includes “Frameworks/_hashlib.framework/_hashlib.cpython-39-iphoneos.dylib”, which includes BoringSSL / openssl_grpc, an SDK that was identified in the documentation as a commonly used third-party SDK. If a new app includes a commonly used third-party SDK, or an app update adds a new commonly used third-party SDK, the SDK must include a privacy manifest file. Please contact the provider of the SDK that includes this file to get an updated SDK version with a privacy manifest. For more details about this policy, including a list of SDKs that are required to include signatures and manifests, visit: https://developer.apple.com/support/third-party-SDK-requirements.
ITMS-91061: Missing privacy manifest - Your app includes “Frameworks/_ssl.framework/_ssl.cpython-39-iphoneos.dylib”, which includes BoringSSL / openssl_grpc, an SDK that was identified in the documentation as a commonly used third-party SDK. If a new app includes a commonly used third-party SDK, or an app update adds a new commonly used third-party SDK, the SDK must include a privacy manifest file. Please contact the provider of the SDK that includes this file to get an updated SDK version with a privacy manifest. For more details about this policy, including a list of SDKs that are required to include signatures and manifests, visit: https://developer.apple.com/support/third-party-SDK-requirements.
The two libraries that are being flagged are libraries that link against OpenSSL, which has been flagged by Apple as an SDK that require(s) a privacy manifest and signature.
I haven't confirmed if this is also the case for the Mac App Store, but it seems highly likely that it will be.
The documentation for Privacy Manifests suggests that OpenSSL itself should be responsible for providing the privacy manifest; but it also assumes that OpenSSL will be used as an XCframework, rather than being linked and redistributed as a dynamic library. It definitely doesn't cover the iOS use case of "static linking and build-time relocation into the Frameworks folder".
OpenSSL has addressed this for macOS Framework builds; but has indicated that because they don't produce official iOS builds, they aren't going to fix the problem for iOS.
- Add an Apple privacy info file for OpenSSL openssl/openssl#24260 adds a candidate PrivacyInfo file for macOS builds
- OpenSSL iOS Privacy Manifest openssl/openssl#23262 is a discussion about the requirement for iOS
- iOS: Support Apple Privacy Manifest openssl/openssl#23494 is a report on OpenSSL's repo about this issue on iOS
macOS isn't using OpenSSL.framework, so the implication is that this PrivacyInfo file would need to be incorporated into Python.framework. More investigation is required (including confirming whether this is actually a problem for the macOS App Store).
Based on what I've seen so far, it seems like the iOS solution will be to incorporate PrivacyInfo handling into the framework build script, and include the PrivacyInfo file next to the .so files that are being processed by the Xcode build handling. It seems likely that the macOS privacy manifest can also be used on iOS.
A very suboptimal workaround is to delete the problem files so they aren't included in a packaged app. This is only a viable workaround if you're not using the ssl or hashlib module (directly or indirectly).
CPython versions tested on:
3.13 - but it likely affects all supported CPython versions, as OpenSSL has been a dependency for a long time.
Operating systems tested on:
iOS
Activity
freakboy3742 commentedon Apr 2, 2025
Tagging @ned-deily and @ronaldoussoren for awareness.
ronaldoussoren commentedon Apr 2, 2025
If I read the rejection message correctly this is not just an OpenSSL issue, but affects all 3th-party code we ship in binary distributions and more importantly also Python itself (e.g. if BeeWare's plans for world domination work out Python itself will end up on Apple's list of commonly used 3th-party frameworks).
freakboy3742 commentedon Apr 2, 2025
It's not just an OpenSSL issue - but it's not every 3rd-party library either.
_bzip2,_ctypesand_lzmadon't trigger submission errors, even though they're dependent onbz2,libffiandxzrespectively. It's only the libraries on the specific third-party list that trigger the problem, and the only one that intersects with Python is OpenSSL.A third-party binary wheel that used one of those libraries would also be a problem; but (a) that's then in the domain of a problem to be solved by that third party, and (b) based on what I understand at present, it should be possible to integrate generic "copy xcprivacy file that matches the name of a .so if it exists" logic into the Xcode build scripts.
If Python ever ends up on the list, then we'll be in a position to provide an XCPrivacy file, same as OpenSSL now does.
ned-deily commentedon Apr 4, 2025
Thanks for the heads-up. For others reading this, FTR the cPython release team doesn't currently release anything via Apple's macOS App Store (or the iOS App Store) and thus this issue wouldn't directly affect our release process. I suppose it could affect downstream users who might embed or repackage our macOS binaries but they would likely have other App Store issues to deal with.
freakboy3742 commentedon Apr 4, 2025
Agreed there's no impact on macOS distribution based on the artefacts CPython is currently releasing. There might be in the context of a fix for #86680, which is something I'm hoping to look at in the not too distant future - but then, there will also be issues like #129247 to contend with.
freakboy3742 commentedon May 10, 2025
I have found the solution to this problem, confirmed by submitting an update to TravelTips to the App Store.
During the build process, when
lib-dynload/_hashlib.cpython-3XX-iphoneos.soandlib-dynload/_ssl.cpython-3XX-iphoneos.soare converted into Frameworks, an additional file must be placed in the generated Framework, alongside the renamed binary.The file must be called
PrivacyInfo.xcprivacy; the contents of the file must be:So - the app bundle should contain (amongst many other files):
This specific
PrivacyInfo.xcprivacyfile is only needed for library that statically link OpenSSL. Most libraries will not need anPrivacyInfo.xcprivacyfile; only those that link one of the "known privacy issue" third-party libraries must include the file. However, the contents of that file will be specific to the library being linked.The XML content provided for the OpenSSL version of
PrivacyInfo.xcprivacycomes from OpenSSL itself. An official macOS OpenSSL framework includes this same file; Python needs to include it explicitly because it's linking statically with OpenSSL.There are two possible solutions for this in the CPython context - in the long term, I think we should probably do both.
Firstly, we can modify the suggested Xcode framework processing script to include a step that looks for a
LIBNAME.xcprivacyfile adjacent toLIBNAME.cpython-313-iphoneos.soduring the framework conversion process, and if it exists, moves that file into the framework. This would allow Python - or any other binary library - to provide an xcprivacy file for the libraries that require it, and have that file included in the packaged app.Secondly, we could modify CPython to dynamically link OpenSSL on iOS. We would then be relying on OpenSSL's own xcprivacy file, so no post-processing would be needed for Python itself - however, the post-processing capability would likely still need to exist for any other library that triggered privacy concerns. Dynamically linking OpenSSL would have the additional benefit of (a) removing the need for third-party crypto libraries (like Cryptography) to statically link OpenSSL, and (b) removes OpenSSL security issues from Python's bailiwick.
The downside/limitation of this approach is that there's no official OpenSSL binary for iOS at this time, so we would need to either work with the OpenSSL team to get that added, or someone would need to provide OpenSSL iOS binaries on a third-party basis (upon which Python users would then be dependent).
ned-deily commentedon May 10, 2025
Perhaps there is yet another reason for dynamically linking OpenSSL on iOS: at least in macOS builds, OpenSSL provides two libraries,
libsslandlibcrypto, andlibcryptois linked to from both the_ssl.soand_hashlib.soextension modules in the standard library. So presumably, with static linking, two copies oflibcryptoare being included in such a Python distribution?freakboy3742 commentedon May 10, 2025
Yes - de-duping
libcryptoin the two extension modules would be another advantage (and an additional space saving on top of the de-duplication if a third-party library also links againstlibcryptoand/orlibssl).gh-132006: Add support for handling XCPrivacy manifests (#139163)
pythongh-132006: Add support for handling XCPrivacy manifests (python…
[3.14] gh-132006: Add support for handling XCPrivacy manifests (GH-13…
[3.10] pythongh-132006: Add support for handling XCPrivacy manifests (p…
[3.11] pythongh-132006: Add support for handling XCPrivacy manifests (p…
[3.12] pythongh-132006: Add support for handling XCPrivacy manifests (p…
[3.13] pythongh-132006: Add support for handling XCPrivacy manifests (p…
[3.13] pythongh-132006: Add support for handling XCPrivacy manifests (p…
[3.11] pythongh-132006: Add support for handling XCPrivacy manifests (p…
[3.12] pythongh-132006: Add support for handling XCPrivacy manifests (p…
[3.13] pythongh-132006: Add support for handling XCPrivacy manifests (p…
[3.12] pythongh-132006: Add support for handling XCPrivacy manifests (p…
[3.11] pythongh-132006: Add support for handling XCPrivacy manifests (p…
[3.13] pythongh-132006: Add support for handling XCPrivacy manifests (p…
[3.12] pythongh-132006: Add support for handling XCPrivacy manifests (p…