Privacy manifest files(隐私清单文件)
苹果关于隐私审核政策更新,所有于2024/05/01之后提交审核时,必须包含隐私清单文件,部分三方SDK也必须包含隐私清单和签名(developer.apple.com/cn/support/…),此举是为了App收集数据对用户更加透明化。
一、项目隐私清单
从2024年春季开始,提交审核的App,如果未包含隐私清单,则开发者会收到一封应用提交异常的邮件,邮件主要内容包括:
ITMS-91053: Missing API declaration - Your app’s code in the “xx” file references one or more APIs that require reasons, including the following API categories: NSPrivacyAccessedAPICategoryDiskSpace. While no action is required at this time, starting May 1, 2024, when you upload a new app or app update, you must include a NSPrivacyAccessedAPITypes array in your app’s privacy manifest to provide approved reasons for these APIs used by your app’s code. For more details about this policy, including a list of required reason APIs and approved reasons for usage, visit: developer.apple.com/documentati….
ITMS-91053: Missing API declaration - Your app’s code in the “xx” file references one or more APIs that require reasons, including the following API categories: NSPrivacyAccessedAPICategorySystemBootTime. While no action is required at this time, starting May 1, 2024, when you upload a new app or app update, you must include a NSPrivacyAccessedAPITypes array in your app’s privacy manifest to provide approved reasons for these APIs used by your app’s code. For more details about this policy, including a list of required reason APIs and approved reasons for usage, visit: developer.apple.com/documentati….
ITMS-91053: Missing API declaration - Your app’s code in the “xx” file references one or more APIs that require reasons, including the following API categories: NSPrivacyAccessedAPICategoryFileTimestamp. While no action is required at this time, starting May 1, 2024, when you upload a new app or app update, you must include a NSPrivacyAccessedAPITypes array in your app’s privacy manifest to provide approved reasons for these APIs used by your app’s code. For more details about this policy, including a list of required reason APIs and approved reasons for usage, visit: developer.apple.com/documentati….
ITMS-91053: Missing API declaration - Your app’s code in the “xx” file references one or more APIs that require reasons, including the following API categories: NSPrivacyAccessedAPICategoryUserDefaults. While no action is required at this time, starting May 1, 2024, when you upload a new app or app update, you must include a NSPrivacyAccessedAPITypes array in your app’s privacy manifest to provide approved reasons for these APIs used by your app’s code. For more details about this policy, including a list of required reason APIs and approved reasons for usage, visit: developer.apple.com/documentati….
1.1、创建隐私清单
- Xcode升级至Xcode15.x
- 新建文件
Command + N - 文件名称无需改动,私用默认名称即可(PrivacyInfo.xcprivacy)
1.2、隐私清单类别
隐私清单配置主要类别:
-
NSPrivacyTracking
一个布尔值,指示您的应用程序或第三方
SDK是否使用应用程序跟踪透明度框架(AppTrackingTransparency,简称:ATT)下定义的数据进行跟踪。如果APP内使用了ATT的数据存在跟踪行为,则此选项必须为true,否则即使使用了ATT,此选项可为false。更多信息请参阅:developer.apple.com/app-store/u…。 -
NSPrivacyTrackingDomains
一组字符串,列出您的应用或第三方
SDK连接到的参与跟踪的互联网域。如果用户未通过应用程序跟踪透明度框架授予跟踪权限,则对这些域的网络请求将失败,并且您的应用程序会收到错误。如果您设置
NSPrivacyTracking为true,则您需要在NSPrivacyTrackingDomains中提供至少一个互联网域;否则,您可以提供零个或多个域。 -
NSPrivacyCollectedDataTypes
描述您的应用程序或第三方
SDK收集的数据类型的字典数组。有关字典中使用的键和值的信息,请参阅:developer.apple.com/documentati… -
NSPrivacyAccessedAPITypes
一组字典,描述您的应用或第三方
SDK访问的API类型,这些类型已被指定为需要访问原因的API。有关字典中要使用的键和值的信息,请参阅:developer.apple.com/documentati…。
1.3、隐私清单添加类别
添加上述类别后,如下图:
针对某一类别,需要单独处理:
1.3.1 NSPrivacyTracking(Privacy Tracking Enable)
- 是否必要:非必要项
- 使用跟踪透明度框架:AppTrackingTransparency,即ATT。则此项必须为
True。 - 使用
IDFV,此项不必设置为True,但使用需要合规。 - 获取
IDFV
NSString *idfv = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
- 获取
IDFA
NSString *idfa = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
1.3.2 NSPrivacyTrackingDomains(Privacy Tracking Domains)
- 是否必要:非必要项
- 如果设置
NSPrivacyTracking为True则至少需要设置一个domain,否则可以为0or多个。 - 如果用户未通过
ATT的隐私协议,则Apple会阻止对追踪域(Tracking Domains)的网络请求。 - 可以通过Xcode -> Open Developer Tool -> Instruments -> Network -> Points Of Interest,查看详情,图片截取自 WWDC23 session,地址:developer.apple.com/videos/play…
1.3.3 NSPrivacyCollectedDataTypes(Privacy Nutrition Label Types)
- 是否必要:非必要项
- NSPrivacyCollectedDataType(Collected Data Type)
- String,用于标识您的应用或第三方
SDK收集的数据类型。从下面的数据类型列表中选择与您的应用或第三方SDK收集的数据相匹配的值。 - 链接地址:developer.apple.com/documentati…
- String,用于标识您的应用或第三方
- NSPrivacyCollectedDataTypeLinked(Linked to User)
- Bool,应用程序或第三方
SDK是否将此数据类型链接到用户的身份。 - 链接地址:developer.apple.com/app-store/a…
- Bool,应用程序或第三方
- NSPrivacyCollectedDataTypeTracking(Used for Tracking)
- Bool,应用程序或第三方
SDK是否使用此数据类型进行跟踪。
- Bool,应用程序或第三方
- NSPrivacyCollectedDataTypePurposes(Collection Purposes)
- 应用或第三方
SDK收集数据的原因的字符串数组。从下面的目的列表中选择与您的应用或第三方SDK收集此数据类型的原因相匹配的值。 - 链接地址:developer.apple.com/app-store/a…
- 应用或第三方
1.3.4 NSPrivacyAccessedAPITypes(Privacy Accessed API Types)
- 是否必要:必要项
- Dictionary,描述应用或第三方
SDK访问的API类型,这些类型已被指定为需要访问原因的API。有关字典中要使用的键和值的信息,请参阅描述:developer.apple.com/documentati… - NSPrivacyAccessedAPIType
- String,标记应用程序必要理由的api类型
- NSPrivacyAccessedAPITypeReasons
- String,应用程序使用
API的原因
- String,应用程序使用
1.3.4.1 File timestamp APIs(File Timestamp)
以下用于访问文件时间戳的API需要使用原因。使用字符串NSPrivacyAccessedAPICategoryFileTimestamp作为NSPrivacyAccessedAPIType键在你的NSPrivacyAccessedAPITypes字典中的值。
- NSFileCreationDate
- NSFileModificationDate
- fileModificationDate
- NSURLContentModificationDateKey
- NSURLCreationDateKey
- getattrlist(::::_:)
- getattrlistbulk(::::_:)
- fgetattrlist(::::_:)
- stat
- fstat(::)
- fstatat(::::)
- lstat(::)
- getattrlistat(::::::)
在您的数组中,提供此列表中的相关值。NSPrivacyAccessedAPITypeReasons
- DDA9.1
声明此原因以向使用该设备的人员显示文件时间戳。
出于此原因访问的信息或任何派生信息可能不会发送到设备外。
- C617.1
声明此原因以访问应用程序容器、应用程序组容器或应用程序的CloudKit容器内的文件的时间戳、大小或其他元数据。
- 3B52.1
声明此原因以访问用户明确授予访问权限的文件或目录的时间戳、大小或其他元数据,例如使用文档选择器视图控制器。
- 0A2A.1
如果您的第三方SDK提供文件时间戳API的包装函数供应用程序使用,并且您仅在应用程序调用您的包装函数时访问文件时间戳API,请声明此原因。此原因只能由第三方SDK声明。如果您的第三方SDK主要是为了包装所需的原因API而创建的,则可能不会声明此原因。
出于此原因访问的信息或任何派生信息不得用于第三方SDK自身的目的,也不得由第三方SDK发送至设备外。
1.3.4.2 System boot time APIs(System Boot Time)
以下用于访问系统引导时间的API需要使用理由。使用字符串NSPrivacyAccessedAPICategorySystemBootTime作为NSPrivacyAccessedAPIType键在你的NSPrivacyAccessedAPITypes字典中的值。
- systemUptime
- mach_absolute_time ()
在NSPrivacyAccessedAPITypeReasons数组中,从下面的列表中提供相关的值。
- 35F9.1
声明此原因以访问系统启动时间,以便测量应用程序中发生的事件之间经过的时间量,或者执行计算以启用计时器。
因此访问的信息或任何派生信息都不能发送到设备外。关于在应用程序中发生的事件之间经过的时间量的信息有一个例外,这些信息可能会发送到设备外。
- 8FFB.1
声明这个原因来访问系统启动时间,以计算应用程序中发生的事件的绝对时间戳,例如与UIKit或AVFAudio框架相关的事件。
在你的应用程序中发生的事件的绝对时间戳可能会被发送到设备外。由于这个原因访问的系统引导时间,或者从系统引导时间派生的任何其他信息,都不能发送到设备外。
- 3D61.1
声明这个原因,以便在使用设备的人选择提交的可选错误报告中包含系统引导时间信息。系统启动时间信息必须作为报告的一部分显着显示给人员。
为此访问的信息,或任何派生信息,只有在用户确定选择提交特定的错误报告(包括系统启动时间信息)后,才能发送出设备,并且仅用于调查或响应错误报告。
1.3.4.3 Disk space APIs(Disk Space)
以下用于访问可用磁盘空间的API需要使用理由。使用字符串NSPrivacyAccessedAPICategoryDiskSpace作为NSPrivacyAccessedAPIType键在你的NSPrivacyAccessedAPITypes字典中的值。
- NSURLVolumeAvailableCapacityKey
- NSURLVolumeAvailableCapacityForImportantUsageKey
- NSURLVolumeAvailableCapacityForOpportunisticUsageKey
- NSURLVolumeTotalCapacityKey
- NSFileSystemFreeSize
- NSFileSystemSize
- statfs(::)
- statvfs(::)
- fstatfs(::)
- fstatvfs(::)
- getattrlist(::::_:)
- fgetattrlist(::::_:)
- getattrlistat(::::::)
在NSPrivacyAccessedAPITypeReasons数组中,从下面的列表中提供相关的值。
- 85F4.1
声明此原因以向使用该设备的人显示磁盘空间信息。磁盘空间可以以信息单位(如字节)或与媒体类型相结合的时间单位(如高清视频的分钟数)显示。
因此访问的信息或任何派生信息都不能发送到设备外。有一个例外,允许应用程序通过本地网络将磁盘空间信息发送到由同一个人操作的另一个设备,仅用于在该设备上显示磁盘空间信息;此例外仅适用于用户提供了发送磁盘空间信息的明确许可,并且该信息不能通过Internet发送。
- E174.1
声明这个原因是为了检查是否有足够的磁盘空间来写文件,或者检查磁盘空间是否不足,以便在磁盘空间不足时应用程序可以删除文件。应用程序必须以用户可观察到的方式根据磁盘空间表现出不同的行为。
因此访问的信息或任何派生信息都不能发送到设备外。有一个例外,允许应用程序在磁盘空间不足时避免从服务器下载文件。
- 7D9E.1
声明这个原因,以便在使用设备的人选择提交的可选错误报告中包含磁盘空间信息。磁盘空间信息必须作为报告的一部分显着显示给人员。
为此访问的信息或任何派生信息,只有在用户确定选择提交包含磁盘空间信息的特定错误报告后,才能发送出设备,并且仅用于调查或响应错误报告。
- B728.1
如果您的应用程序是健康研究应用程序,请声明此原因,并访问此API类别以检测并通知研究参与者低磁盘空间影响研究数据收集。
你的应用必须符合app Store审核指南§5.1.3。你的应用程序除了提供信息和允许人们参与健康研究之外,不能提供任何其他功能。
1.3.4.4 Active keyboard APIs(Active Keyboards)
以下用于访问活动键盘列表的API需要使用理由。使用字符串NSPrivacyaccessedAPICategoryActiveKeyboard作为NSPrivacyAccessedAPIType键在你的NSPrivacyAccessedAPITypes字典中的值。
- activeInputModes
在NSPrivacyAccessedAPITypeReasons数组中,从下面的列表中提供相关的值。
- 3EC4.1
如果你的应用是一个自定义键盘应用,声明这个原因,你访问这个API类别来确定设备上激活的键盘。
为用户提供系统范围的自定义键盘必须是应用程序的主要功能。
因此访问的信息或任何派生信息都不能发送到设备外。
- 54BD.1
声明此原因以访问活动键盘信息,从而向使用该设备的人呈现正确的自定义用户界面。应用程序必须具有用于输入或编辑文本的文本字段,并且必须以用户可观察到的方式基于活动键盘表现出不同的行为。 因此访问的信息或任何派生信息都不能发送到设备外。
1.3.4.5 User defaults APIs(User Defaults)
以下用于访问用户默认值的API需要使用原因。使用字符串NSPrivacyAccessedAPICategoryUserDefaults作为NSPrivacyAccessedAPIType键在你的NSPrivacyAccessedAPITypes字典中的值。
- NSUserDefaults
在NSPrivacyAccessedAPITypeReasons数组中,从下面的列表中提供相关的值。
- CA92.1
声明这个原因来访问用户默认值,读取和写入只有应用程序本身可以访问的信息。 这个原因不允许读取其他应用程序或系统写入的信息,也不允许写入其他应用程序可以访问的信息。
- 1C8F.1
声明这个原因来访问用户默认的读写信息,这些信息只能被应用程序、应用程序扩展和应用程序剪辑访问,它们是与应用程序本身相同的应用程序组的成员。
这个原因不允许读取由同一应用程序组之外的应用程序、应用程序扩展或应用程序剪辑编写的信息。如果系统提供来自全局域的信息,因为当您的应用程序试图读取应用程序,应用程序扩展或应用程序剪辑在应用程序的应用程序组中编写的信息时,密钥不存在于您请求的域,则您的应用程序不负责。
这个原因也不允许编写可以被同一应用程序组之外的应用程序、应用程序扩展或应用程序剪辑访问的信息。
- C56D.1
如果您的第三方SDK为应用程序提供了用户默认API的包装器函数,并且只有在应用程序调用您的包装器函数时才访问用户默认API,请声明此原因。这个原因只能由第三方SDK声明。如果您的第三方SDK主要用于包装所需的原因API,则可能不会声明此原因。
出于此原因访问的信息或任何派生信息不得用于您的第三方SDK自己的目的,也不得由您的第三方SDK发送到设备外。
- AC6B.1
声明此原因是为了访问用户默认值以读取com.apple.configuration.managed键来检索MDM设置的托管应用程序配置,或者设置com.apple.feedback.managed键来存储要在MDM上查询的反馈信息,如Apple Mobile Device Management Protocol Reference文档中所述。
二、SDK隐私清单与签名
SDK开发者需提供包含签名的SDK。App中采用第三方SDK的新版本时,Xcode将验证SDK供应链的安全性。
签名类型:
Apple Developer Program签名SDK开发者在编译SDK时进行签名操作
- 自签名
- 对已存在的
SDK进行签名操作 - 参考地址:www.yuque.com/ibabyblue/i…
- 对已存在的
SDK签名认证后 ,在Xcode中会显示对应的签名信息,如果发现签名和预期不一致,Xcode就会让编译失败并弹出警告。下图是截取自WWDC2023 session,地址:developer.apple.com/videos/play…
Apple建议所有SDK使用签名, 如果是在苹果三方SDK列表中的作为二进制依赖项,必须提供签名。
苹果官方发布的必须包含隐私清单和签名SDK列表地址:
developer.apple.com/cn/support/…
三、参考
developer.apple.com/documentati… developer.apple.com/cn/support/… developer.apple.com/videos/play… developer.apple.com/videos/play…