https://github.com/python/cpython/commit/195d13c85e17ab5cf6ac2a6de098bbf514cae207
commit: 195d13c85e17ab5cf6ac2a6de098bbf514cae207
branch: main
author: Russell Keith-Magee <[email protected]>
committer: freakboy3742 <[email protected]>
date: 2025-09-29T05:50:46+08:00
summary:

gh-132006: Add support for handling XCPrivacy manifests (#139163)

Adds a PrivacyInfo.xcprivacy file when packaging `_hashlib` and `_ssl` modules
for iOS (based on the original OpenSSL sources); and adds handling to the build
script to allow any app to add `xcprivacy` handling for a binary module.

files:
A Misc/NEWS.d/next/Tools-Demos/2025-08-28-06-22-26.gh-issue-132006.eZQmc6.rst
M Apple/__main__.py
M Apple/testbed/Python.xcframework/build/utils.sh
M Doc/using/ios.rst

diff --git a/Apple/__main__.py b/Apple/__main__.py
index fc19b31be97bb2..88b54e91ac84d6 100644
--- a/Apple/__main__.py
+++ b/Apple/__main__.py
@@ -316,7 +316,7 @@ def unpack_deps(
     for name_ver in [
         "BZip2-1.0.8-2",
         "libFFI-3.4.7-2",
-        "OpenSSL-3.0.16-2",
+        "OpenSSL-3.0.17-1",
         "XZ-5.6.4-2",
         "mpdecimal-4.0.0-2",
         "zstd-1.5.7-1",
@@ -577,6 +577,7 @@ def create_xcframework(platform: str) -> str:
 
     # Extract the package version from the merged framework
     version = package_version(package_path / "Python.xcframework")
+    version_tag = ".".join(version.split(".")[:2])
 
     # On non-macOS platforms, each framework in XCframework only contains the
     # headers, libPython, plus an Info.plist. Other resources like the standard
@@ -647,6 +648,23 @@ def create_xcframework(platform: str) -> str:
                 slice_framework / f"Headers/pyconfig-{arch}.h",
             )
 
+            # Apple identifies certain libraries as "security risks"; if you
+            # statically link those libraries into a Framework, you become
+            # responsible for providing a privacy manifest for that framework.
+            xcprivacy_file = {
+                "OpenSSL": subdir(host_triple) / 
"prefix/share/OpenSSL.xcprivacy"
+            }
+            print(f"   - {multiarch} xcprivacy files")
+            for module, lib in [
+                ("_hashlib", "OpenSSL"),
+                ("_ssl", "OpenSSL"),
+            ]:
+                shutil.copy(
+                    xcprivacy_file[lib],
+                    slice_path
+                    / 
f"lib-{arch}/python{version_tag}/lib-dynload/{module}.xcprivacy",
+                )
+
     print(" - build tools")
     shutil.copytree(
         PYTHON_DIR / "Apple/testbed/Python.xcframework/build",
diff --git a/Apple/testbed/Python.xcframework/build/utils.sh 
b/Apple/testbed/Python.xcframework/build/utils.sh
index 9cfe74720f26d4..961c46d014b5f5 100755
--- a/Apple/testbed/Python.xcframework/build/utils.sh
+++ b/Apple/testbed/Python.xcframework/build/utils.sh
@@ -67,6 +67,9 @@ install_dylib () {
 
     # The name of the extension file
     EXT=$(basename "$FULL_EXT")
+    # The name and location of the module
+    MODULE_PATH=$(dirname "$FULL_EXT")
+    MODULE_NAME=$(echo $EXT | cut -d "." -f 1)
     # The location of the extension file, relative to the bundle
     RELATIVE_EXT=${FULL_EXT#$CODESIGNING_FOLDER_PATH/}
     # The path to the extension file, relative to the install base
@@ -94,6 +97,16 @@ install_dylib () {
     # Create a back reference to the .so file location in the framework
     echo "${RELATIVE_EXT%.so}.fwork" > 
"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME.origin"
 
+    # If the framework provides an xcprivacy file, install it.
+    if [ -e "$MODULE_PATH/$MODULE_NAME.xcprivacy" ]; then
+        echo "Installing XCPrivacy file for 
$FRAMEWORK_FOLDER/$FULL_MODULE_NAME"
+        
XCPRIVACY_FILE="$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/PrivacyInfo.xcprivacy"
+        if [ -e "$XCPRIVACY_FILE" ]; then
+          rm -rf "$XCPRIVACY_FILE"
+        fi
+        mv "$MODULE_PATH/$MODULE_NAME.xcprivacy" "$XCPRIVACY_FILE"
+    fi
+
     echo "Signing framework as $EXPANDED_CODE_SIGN_IDENTITY_NAME 
($EXPANDED_CODE_SIGN_IDENTITY)..."
     /usr/bin/codesign --force --sign "$EXPANDED_CODE_SIGN_IDENTITY" 
${OTHER_CODE_SIGN_FLAGS:-} -o runtime --timestamp=none 
--preserve-metadata=identifier,entitlements,flags --generate-entitlement-der 
"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER"
 }
diff --git a/Doc/using/ios.rst b/Doc/using/ios.rst
index c02dac444dd7cc..5e4033fb6cec7a 100644
--- a/Doc/using/ios.rst
+++ b/Doc/using/ios.rst
@@ -328,7 +328,12 @@ App Store Compliance
 The only mechanism for distributing apps to third-party iOS devices is to
 submit the app to the iOS App Store; apps submitted for distribution must pass
 Apple's app review process. This process includes a set of automated validation
-rules that inspect the submitted application bundle for problematic code.
+rules that inspect the submitted application bundle for problematic code. There
+are some steps that must be taken to ensure that your app will be able to pass
+these validation steps.
+
+Incompatible code in the standard library
+-----------------------------------------
 
 The Python standard library contains some code that is known to violate these
 automated rules. While these violations appear to be false positives, Apple's
@@ -339,3 +344,18 @@ The Python source tree contains
 :source:`a patch file <Mac/Resources/app-store-compliance.patch>` that will 
remove
 all code that is known to cause issues with the App Store review process. This
 patch is applied automatically when building for iOS.
+
+Privacy manifests
+-----------------
+
+In April 2025, Apple introduced a requirement for `certain third-party
+libraries to provide a Privacy Manifest
+<https://developer.apple.com/support/third-party-SDK-requirements>`__.
+As a result, if you have a binary module that uses one of the affected
+libraries, you must provide an ``.xcprivacy`` file for that library.
+OpenSSL is one library affected by this requirement, but there are others.
+
+If you produce a binary module named ``mymodule.so``, and use you the Xcode
+build script described in step 7 above, you can place a ``mymodule.xcprivacy``
+file next to ``mymodule.so``, and the privacy manifest will be installed into
+the required location when the binary module is converted into a framework.
diff --git 
a/Misc/NEWS.d/next/Tools-Demos/2025-08-28-06-22-26.gh-issue-132006.eZQmc6.rst 
b/Misc/NEWS.d/next/Tools-Demos/2025-08-28-06-22-26.gh-issue-132006.eZQmc6.rst
new file mode 100644
index 00000000000000..8e7910768648a0
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Tools-Demos/2025-08-28-06-22-26.gh-issue-132006.eZQmc6.rst
@@ -0,0 +1,2 @@
+XCframeworks now include privacy manifests to satisfy Apple App Store
+submission requirements.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to