Apple designed the “Required Reason” API to enhance user privacy and trust. It helps ensure that app developers clearly communicate the reasons for requesting access to personal data or certain device capabilities. The guideline is now active for almost a year, and we’ve observed that this approach seems to generally work. But in practice, we observe some developers sneaking around these restrictions without Apple acknowledging this fact.
![](https://blog.appicaptor.com/wp-content/uploads/2025/01/appleDefense2.png)
As we approach the first anniversary of Apple’s Required Reasons API, we feel it’s time to recap it’s privacy gains in practice.
For developers, the Required Reasons API acts as a gatekeeper into the app store. It requires them to provide clear justifications for using certain APIs that access sensitive user data or system capabilities. The users can then inspect and evaluate the provided reason during app install. The principle behind this API is to promote transparency and user control over personal data. A significant contribution is the seamless integration of third-party library required reasons into the main app. This has ensured that the privacy measures extend beyond the core app, covering all the integrated elements.
Diving into the Details: Boot Time Example
To illustrate this, let’s take the example of boot time. The boot time of a device in microseconds is unique and can easily be used for device identification. Thus, such data requires sufficient protection to hinder device fingerprinting and therewith protecting the user’s privacy. Apple has identified two boot time related APIs: systemUptime
and mach_absolute_time()
. These require developers to provide specified reasons for their use. Apps or libraries accessing these methods must provide a reason in the app’s/library’s Info.plist
file. This XML-file contains among other things a key specifying a resource linked with a reason for accessing this resource. Apple provides different short identifiers which specify a usage purpose as shown here:
<key>NSPrivacyAccessedAPICategorySystemBootTime</key>
<string>35F9.1</string>
In this example, the short identifier specifies the following reason, documented by Apple:
“Declare this reason to access the system boot time in order to measure the amount of time that has elapsed between events that occurred within the app or to perform calculations to enable timers. Information accessed for this reason, or any derived information, may not be sent off-device. There is an exception for information about the amount of time that has elapsed between events that occurred within the app, which may be sent off-device.”
A Year of Practice: The Good…
To evaluate these advancements in practice, we have collected the most popular third-party libraries for iOS apps. Next, we searched for libraries, known for device fingerprinting activities. The Required Reason API typically impacts such libraries the most, since they heavily rely on this data. In practice, the top three libraries leveraging device fingerprinting techniques make up more than 80% market share. Thus, analysing the top three libraries already provides broad coverage. We found that the top three libraries in fact use APIs from the “Required Reasons API” list, but provide a proper reason declaration. This means, that whenever a respective API is used, an appropriate cause in the Info.plist
is provided. Thus, developers are adhering to the rules, and/or Apple is effectively enforcing these rules in the App Store.
…and the Bad
However, we have observed instances in some used libraries where developers have found ways around these obligations. These libraries use other methods for querying boot time, such as sysctl
and sysctlbyname
.
In iOS, sysctl
and sysctlbyname
are system calls enabling access to kernel parameters at runtime. They allow developers to query essential information about the system, such as CPU and memory statistics or the boot time. The sysctlbyname
call offers a more user-friendly access method by using string identifiers instead of integers. Thus, an alternative way to query the boot time with this function would be:
sysctlbyname("kern.boottime", &bootTime, &size, nil, 0)
Additionally enforcing these APIs would require evaluating the arguments during the static analysis in Apple’s app publishing process. Evaluating the arguments during a static code analysis can sometimes be complicated if the argument isn’t a constant. Advanced techniques like symbolic execution or data dependency analysis might be necessary, features already applied in Appicaptor.
We have already contacted Apple on May 2nd, 2024 and informed them about missing items in their Required Reason API. However, they did not respond up until this day. We think that Apple is well aware of these APIs but doesn’t want to confirm this due to political reasons.
The Road Ahead
In conclusion, we see that Apple strides in the right direction, but there are still loopholes that need to be addressed. We look forward to seeing Apple continue to enhance its privacy measures, closing remaining gaps. Meanwhile, we continue to monitor Apple’s Required Reason APIs usage with Appicaptor and check for violations.