Skip to content

Apple App Store rejecting apps because of "(ITMS-91061) Missing privacy manifest" #132006

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
freakboy3742 opened this issue Apr 2, 2025 · 8 comments
Assignees
Labels
3.13 bugs and security fixes 3.14 bugs and security fixes OS-ios OS-mac type-bug An unexpected behavior, bug, or error

Comments

@freakboy3742
Copy link
Contributor

freakboy3742 commented Apr 2, 2025

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.

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

@freakboy3742 freakboy3742 added 3.13 bugs and security fixes 3.14 bugs and security fixes OS-ios OS-mac type-bug An unexpected behavior, bug, or error labels Apr 2, 2025
@freakboy3742 freakboy3742 self-assigned this Apr 2, 2025
@freakboy3742
Copy link
Contributor Author

Tagging @ned-deily and @ronaldoussoren for awareness.

@ronaldoussoren
Copy link
Contributor

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
Copy link
Contributor Author

freakboy3742 commented Apr 2, 2025

It's not just an OpenSSL issue - but it's not every 3rd-party library either. _bzip2, _ctypes and _lzma don't trigger submission errors, even though they're dependent on bz2, libffi and xz respectively. 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
Copy link
Member

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
Copy link
Contributor Author

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
Copy link
Contributor Author

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.so and lib-dynload/_ssl.cpython-3XX-iphoneos.so are 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:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
    <key>NSPrivacyAccessedAPITypes</key>
    <array>
        <dict>
            <key>NSPrivacyAccessedAPIType</key>
            <string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
            <key>NSPrivacyAccessedAPITypeReasons</key>
            <array>
                <string>C617.1</string>
            </array>
        </dict>
    </array>
    <key>NSPrivacyCollectedDataTypes</key>
    <array/>
    <key>NSPrivacyTrackingDomains</key>
    <array/>
    <key>NSPrivacyTracking</key>
    <false/>
    </dict>
</plist>

So - the app bundle should contain (amongst many other files):

  • My App.app
    • Frameworks
      • _hashlib.framework
        • _hashlib
        • _hashlib.origin
        • Privacy.xcprivacy
        • Info.plist
      • _ssl.framework
        • _ssl
        • _ssl.origin
        • Privacy.xcprivacy
        • Info.plist
      • ... other frameworks

This specific PrivacyInfo.xcprivacy file is only needed for library that statically link OpenSSL. Most libraries will not need an PrivacyInfo.xcprivacy file; 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.xcprivacy comes 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.xcprivacy file adjacent to LIBNAME.cpython-313-iphoneos.so during 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
Copy link
Member

Perhaps there is yet another reason for dynamically linking OpenSSL on iOS: at least in macOS builds, OpenSSL provides two libraries, libssl and libcrypto, and libcrypto is linked to from both the _ssl.so and _hashlib.so extension modules in the standard library. So presumably, with static linking, two copies of libcrypto are being included in such a Python distribution?

@freakboy3742
Copy link
Contributor Author

Yes - de-duping libcrypto in 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 against libcrypto and/or libssl).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.13 bugs and security fixes 3.14 bugs and security fixes OS-ios OS-mac type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

3 participants