Does anybody know what the "Document Storage" entry in the Privacy settings for an app means?
I recently discovered that the Privacy Settings of my own app nowadays has a "Document Storage" entry, with (for me) the possible choices: "iCloud Drive", "On My Phone", and "Dropbox". I don't know with which version of iOS these appeared.
When "iCloud Drive" is selected (the default), then the explanatory text below it says "Automatically upload and store your documents in iCloud Drive"
My app has no explicit support for iCloud Drive or iCloud in general, and no support for Dropbox. Some of its files are stored in the Documents folder of the app, which is publicly accessible (through the Files app, e.g.)
My users assume that enabling the option will automatically copy those files to iCloud Drive, but that does not seem to be happening.
I have searched half a day for any documentation around this from Apple, but found nothing.
So: does anybody know what that setting does?
And: if it does not do anything, then how can I can make sure it does NOT appear, to not confuse my users?
General
RSS for tagPrioritize user privacy and data security in your app. Discuss best practices for data handling, user consent, and security measures to protect user information.
Post
Replies
Boosts
Views
Activity
Near the bottom,
Describing data use in privacy manifests, says:
App extensions don’t include privacy information files. The operating system and App Store Connect use the privacy information file in the extension’s host app bundle, in combination with those from third-party SDKs your app links to.
Yet the warnings email we see lists the app's extensions as missing manifests.
Are we reading the documentation incorrectly?
Getting this clarified helps us justify approvals for the additional work.
Issue: The screen saver is not shown, and the user is not locked after removing a smart card with a logged in user.
I have tried setting tokenRemovalAction to 1, along with various other com.apple.security.smartcard defaults, and I have also tried setting "turn on screen saver when login token removed." None of this makes the screen locked on card removal.
Is this an issue with MacOS14 or is there a different setting/value that has to be set for this to work correctly?
Lets say i have an sdk that is not one of those listed, but it uses one of those listed. In this case, do i have to get the sdk im using to update their dependency to add the required signature and privacy manifest?
Hello Apple ID support,
When a user successfully login with Apple, the apple OAuth will produce a appleIdToken. From my understanding this token is best to not leave the user device. I have two sub-system that can take a appleIdToken and manages the token-refresh separately.
In short:
Apple -> appleIdToken
sub-SystemA(appleIdToken) and sub-systemB(appleIdToken)
sub-SystemA and sub-systemB has two separate token management/refresh
The question:
Is this allowed by the Apple identify server?
Is the usecase of supplying appleIdToken to sub-SystemA and sub-systemB valid?
Dear Developer Community,
I recently implemented privacy manifest changes in accordance with Apple guidelines. However, have encountered unexpected issues with BLE communication while our app was running in the background when there are multiple reader.
During local testing in both debug and release modes within Xcode, have not experienced any problems with BLE communication, even with multiple readers.
However, upon uploading the build to TestFlight for testing, i found that communication was being blocked when multiple readers are there. This behavior was quite perplexing.
Upon further investigation, I decided to revert the privacy manifest changes and retested via TestFlight. Surprisingly, we did not encounter any issues with BLE communication.
I am reaching out to this forum to inquire whether anyone else has encountered similar issues with BLE communication. Additionally, I have submitted a report via Feedback Assistant to seek assistance from Apple. I am particularly interested in understanding if any core logic related to BLE is affected by the privacy manifest changes.
As Apple has mandated the inclusion of the privacy manifest for App Store submissions starting from Spring 2024, any insights or assistance on this matter would be greatly appreciated.
I had implemented the Apple login feature and users were fully utilizing it.
Then, all of a sudden, it started to fail with an "Invalid client scope
" error.
And My code is exactly scope="name email".
I haven't changed any code for Apple Login, so why is this suddenly happening?
Is it possible?
The original key was generated and stored in the Keychain using the following code:
func generateSecureEnclaveProtectedSecKey(withTag tag: Data) throws -> SecKey {
var error: Unmanaged<CFError>?
let accessControl = SecAccessControlCreateWithFlags(
kCFAllocatorDefault,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
[.privateKeyUsage],
&error
)!
let attributes = [
kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeySizeInBits as String: 256,
kSecAttrTokenID as String: kSecAttrTokenIDSecureEnclave,
kSecPrivateKeyAttrs as String: [
kSecAttrCanSign as String: true,
kSecAttrIsPermanent as String: true,
kSecAttrApplicationTag as String: tag,
kSecAttrAccessControl as String: accessControl,
] as [String: Any],
] as [String: Any]
let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error)!
return privateKey
}
Then I wanted to use the strongly typed interface of CryptoKit, so I naively tried to get a hold of the existing key as follows (querying for kSecReturnPersistentRef and not kSecReturnRef):
func getSecureEnclaveProtectedCryptoKitKey(fromSecureEnclaveProtectedSecKeyWithTag tag: Data) throws -> SecureEnclave.P256.Signing.PrivateKey {
let query: [String: Any] = [
kSecClass as String: kSecClassKey,
kSecAttrApplicationTag as String: tag,
kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
kSecReturnPersistentRef as String: true,
]
var item: CFTypeRef?
let status = SecItemCopyMatching(query as CFDictionary, &item)
let keyData = item as! CFData
return try SecureEnclave.P256.Signing.PrivateKey(dataRepresentation: keyData as Data)
}
But that resulted in:
Error Domain=CryptoTokenKit Code=-3 "corrupted objectID detected" UserInfo={NSLocalizedDescription=corrupted objectID detected}
Since this is a Secure Enclave protected key, it is not possible to use SecKeyCopyExternalRepresentation (or query for kSecReturnData), but perhaps there is another way to convert a SecKey object to a SecureEnclave.P256.Signing.PrivateKey?
The other way around seem to be possible using the answers to this blog post: https://developer.apple.com/forums/thread/728314
My background audio app stops updating its Live Activity after the iPhone locks, and doesn't resume updating the activity after tapping the screen or even after FaceID unlocks the device (without opening the lock screen).
My live activity requests a ContentState update & iOS updates the content for the activity as below:
Task{
log.debug("LiveActivityManager.updateLiveActivity() with new ContentState")
await liveActivity.update( ActivityContent(state:contentState, staleDate:nil) )
}
Below what my log looks like:
<<<<SWIPE LOCK SCREEN DOWN>>>>
DEBUG: LiveActivityManager.updateLiveActivity() with new ContentState
iOS: Updating content for activity 0A519263-1E46-4BB6-BA4F-F3DDBC081AB4
DEBUG: LiveActivityManager.updateLiveActivity() with new ContentState
iOS: Updating content for activity 0A519263-1E46-4BB6-BA4F-F3DDBC081AB4
<<<<PRESS LOCK BUTTON->Lock iPhone>>>>
INFO: --------protectedDataWillBecomeUnavailableNotification--------
DEBUG: LiveActivityManager.updateLiveActivity() with new ContentState
iOS: Updating content for activity 0A519263-1E46-4BB6-BA4F-F3DDBC081AB4
DEBUG: LiveActivityManager.updateLiveActivity() with new ContentState
DEBUG: LiveActivityManager.updateLiveActivity() with new ContentState
DEBUG: LiveActivityManager.updateLiveActivity() with new ContentState
<<<<LOOK AT & TAP LOCK SCREEN->Unlock iPhone without swiping up>>>>
INFO: --------protectedDataDidBecomeAvailableNotification-----------
DEBUG: LiveActivityManager.updateLiveActivity() with new ContentState
DEBUG: LiveActivityManager.updateLiveActivity() with new ContentState
DEBUG: LiveActivityManager.updateLiveActivity() with new ContentState
As shown in the log, normally iOS updates the content for my activity after my liveActivity.update request.
This works fine in the Dynamic Island and when after switching apps and swiping down to see the lock screen without locking the phone.
However, once I lock the phone, iOS stops updating the Live Activity content, and doesn't resume updates until after the app regains the foreground at least once.
Has anyone else encountered this behavior? Is this a setting that I'm missing, or a bug?
I am new to iOS development, and recently I was trying to build an application, which will create a key inside the secure element, and after - I will sing something with it. While developing I've encountered an issue: the key generation fails if there is a flag .biometryAny or .biometryCurrentSet
The authentication itself is triggered, but the function still throws a mistake.
My setup - Xcode iPhone15 simulator, FaceID enrolled and the animation of it is working.
Ive created the same post on overflow, in case somebody will have the same issues:
https://stackoverflow.com/questions/78175858/secure-enclave-key-generation-failure
I've tried deleting the flag, while keeping the manual authorisation, and this approach works, but I still would like have maximum security.
THIS WORKS:
func authenticateUser(completion: @escaping (Bool, Error?) -> Void) {
let context = LAContext()
var error: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
let reason = "Biometric authentication is needed to access your secure data."
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, authenticationError in
DispatchQueue.main.async {
completion(success, authenticationError)
}
}
} else {
// Biometry is not available or not enrolled.
DispatchQueue.main.async {
completion(false, error)
}
}
}
@objc func encryptAction() {
authenticateUser { [weak self] (success, error) in
guard success else {
self?.outputLabel.text = "Authentication failed: \(error?.localizedDescription ?? "Unknown error")"
return
}
guard let randomNumber = self?.inputTextField.text, !randomNumber.isEmpty,
let dataToSign = randomNumber.data(using: .utf8),
let privateKey = self?.generatePrivateKey() else {
self?.outputLabel.text = "Error: Could not generate private key."
return
}
if let signature = self?.signData(privateKey: privateKey, data: dataToSign) {
self?.outputLabel.text = "Signature: \(signature.base64EncodedString())"
} else {
self?.outputLabel.text = "Error: Could not sign data."
}
}
}
func generatePrivateKey() -> SecKey? {
// 1. Create Keys Access Control
guard let accessControl =
SecAccessControlCreateWithFlags(
nil,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
[.privateKeyUsage],
nil)
else {
fatalError("cannot set access control")
}
// 2. Create Key Attributes
guard let tag = "com.example.keys.mykey".data(using: .utf8) else {
fatalError("cannot set tag")
}
let attributes: [String: Any] = [
kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeySizeInBits as String: 256,
kSecAttrTokenID as String: kSecAttrTokenIDSecureEnclave,
kSecPrivateKeyAttrs as String: [
kSecAttrIsPermanent as String: true,
kSecAttrApplicationTag as String: tag,
kSecAttrAccessControl as String: accessControl
]
]
// 3. Generate Key Pairs
var error: Unmanaged<CFError>?
guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {
if let error = error?.takeRetainedValue() {
print("Error creating a key: \(error)")
}
return nil
}
return privateKey
}
func signData(privateKey: SecKey, data: Data) -> Data? {
let digest = sha256(data: data)
var error: Unmanaged<CFError>?
guard let signature = SecKeyCreateSignature(privateKey,
.ecdsaSignatureMessageX962SHA256,
digest as CFData,
&error) as Data? else {
print(error!.takeRetainedValue() as Error)
return nil
}
return signature
}
}
THIS DOESN'T
guard let accessControl =
SecAccessControlCreateWithFlags(
nil,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
[.privateKeyUsage, .biometryCurrentSet],
nil)
else {
info.something file is updated and there is a privacy FaceID field included.
the error is triggered at this part:
var error: Unmanaged<CFError>?
guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {
if let error = error?.takeRetainedValue() {
print("Error creating a key: \(error)")
}
return nil
}
The error itself:
Error creating a key: Error Domain=NSOSStatusErrorDomain Code=-25293 "Key generation failed, error -25293" UserInfo={numberOfErrorsDeep=0, NSDescription=Key generation failed, error -25293}
Suppose I have some third party frameworks integrated in an application. From May inwards, its mandatory to have privacy manifest for all the tracking APIs. But if the third party library doesnt have any plans to integrate the third party framework, how should we proceed to avoid rejection from the app store?
Hello, I’ve got some questions about the privacy manifest.
On March 18, we built our company's app with Xcode 14, submitted it for review, and it passed. However, we did not make any adjustments for the privacy manifest and yet did not receive any related emails. Our app utilizes APIs like UserDefaults and file stamps.
We've got permission from our users to use tracking, so we turned on Xcode15 instruments to check the network, but there were no faults identified in the points of interest. It looks like we’re engaged in tracking activities, possibly with tools like Firebase.
Can someone who knows about this please give me an answer?
Please help me understand the phrasing from Apple's articles about this topic. Of course, I am referring to the SDKs from the official list, as only those are affected by the new regulations.
1, https://developer.apple.com/support/third-party-SDK-requirements/
Starting in spring 2024, you must include the privacy manifest for any SDK listed below when you submit new apps in App Store Connect that include those SDKs, or when you submit an app update that adds one of the listed SDKs as part of the update.
That states 2 cases in which fresh SDK versions are needed, containing privacy information:
If you submit a completely new app
If your app update contains a framework which was not present in the previous version of the app
So, according to my understanding, if I create an app update, which does not contain any new SDKs, only the ones that I have been using for a while now, I can keep using these older SKD versions. And it is not mandatory to update them to newer versions.
Does Apple state anywhere that we have to update every SDK from the list this spring in every case? Because that would contradict what I quoted from the article.
2, https://developer.apple.com/news/?id=3d8a9yyh
And if you add a new third-party SDK that’s on the list of commonly used third-party SDKs, these API, privacy manifest, and signature requirements will apply to that SDK.
Again, this states that you have to use a fresh version of an SDK in case you add it newly to your app. This seems to reinforce my point that if a 3rd party SDK was already used in previous app versions, the new requirements do not apply to that SDK and I can keep using its older release which does not have its own privacy manifest file.
My main concern here is that there are many 3rd party SDKs from the list that we already use in our projects, and it would be a huge effort if my team had to update all those SDKs in every project by May. But if I'm right, it is not mandatory for us. (Of course, it would be wise to update the SDKs every now and then, but that's not the point here.)
Can anybody confirm whether my understanding is correct? Maybe link some proof if I'm not right? It would be nice to have a reply from someone working at Apple, to have a reliable answer.
I use sample code from [https://developer.apple.com/documentation/endpointsecurity/client?language=objc]
but replace ES_EVENT_TYPE_AUTH_EXEC to ES_EVENT_TYPE_AUTH_OPEN, this is the full code:
int main(int argc, const char** argv) {
@autoreleasepool {
es_client_t *client = NULL;
es_new_client_result_t newClientResult =
es_new_client(&client,
^(es_client_t * client, const es_message_t * message) {
switch (message->event_type) {
case ES_EVENT_TYPE_AUTH_OPEN:
printf("auth open\n");
es_respond_auth_result(client, message, ES_AUTH_RESULT_ALLOW, true);
break;
default:
panic("Found unexpected event type: %i", message->event_type);
break;
}
});
// Handle any errors encountered while creating the client.
switch (newClientResult) {
case ES_NEW_CLIENT_RESULT_SUCCESS:
// Client created successfully; continue.
break;
case ES_NEW_CLIENT_RESULT_ERR_NOT_ENTITLED:
panic("Extension is missing entitlement.");
break;
case ES_NEW_CLIENT_RESULT_ERR_NOT_PRIVILEGED:
panic ("Extension is not running as root.");
break;
case ES_NEW_CLIENT_RESULT_ERR_NOT_PERMITTED:
// Prompt user to perform Transparency, Consent,
// and Control (TCC) approval.
// This error is recoverable; the user can try again after
// approving the TCC prompt.
// return YOUR_NEW_CLIENT_ERROR_CODE_PROMPT_TCC;
break;
case ES_NEW_CLIENT_RESULT_ERR_INVALID_ARGUMENT:
panic ("Invalid argument to es_new_client(); client or handler was null.");
break;
case ES_NEW_CLIENT_RESULT_ERR_TOO_MANY_CLIENTS:
panic ("Exceeded maximum number of simultaneously-connected ES clients.");
break;
case ES_NEW_CLIENT_RESULT_ERR_INTERNAL:
panic ("Failed to connect to the Endpoint Security subsystem.");
break;
}
// Subscribe the client to the ES_EVENT_TYPE_AUTH_EXEC event.
// When the client receives a message with this event type, it must authorize
// (allow or deny) the event.
es_event_type_t eventTypes[1] = { ES_EVENT_TYPE_AUTH_OPEN };
es_return_t subscribeResult = es_subscribe(client, eventTypes, sizeof(eventTypes));
if (subscribeResult != ES_RETURN_SUCCESS) {
panic ("Client failed to subscribe to event.");
}
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop run];
}
}
I run this code in xcode, then mouse cursor be a colorful circle and rotating, application exited after about 10 seconds, xcode print:
Message from debugger: Terminated due to signal 9
Program ended with exit code: 9
if I subscribe ES_EVENT_TYPE_NOTIFY_OPEN ES_EVENT_TYPE_NOTIFY_CLOSE, it works.
What can I do for fix this?
1C8F.1 seems to cover all the situations that CA92.1 covers, plus 1C8F.1 covers data for app extensions and App Clips.
If our SDK uses UserDefaults, and our group debates that
some functionality is about data only accessible to the app and would be covered by code CA92.1
some functionality is about data accessible to extensions and App Clips and would be covered by code 1C8F.1
Can we declare both codes in our manifest file (PrivacyInfo.xcprivacy) ?
Or should we only declare 1C8F.1 to cover both parts?
Hello, I have a question regarding the Privacy Manifest of a third-party SDK.
We are using a static third-party SDK. This third-party SDK use the UserDefaults API, and it is also specified in the Privacy Accessed API Types within PrivacyInfo.xcprivacy. The static third-party SDK is added as a dependency via CocoaPods, and PrivacyInfo.xcprivacy is included in the Pods Resource. Additionally, our app does not use UserDefaults API.
When we generate the Privacy Report, it correctly shows the data collected by the third-party SDK. However, when we submitted for review, we received a warning email stating that UserDefaults is being used in the app but is missing from the Privacy Manifest.
ITMS-91053: Missing API declaration - Your app’s code in the “MyApp” 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: https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_use_of_required_reason_api.
I have the following questions:
When submitting the app for review, does Apple not consider the PrivacyInfo.xcprivacy of the third-party SDK?
What steps should be taken to ensure that Apple reviews the PrivacyInfo.xcprivacy of the third-party SDK?
I am developing an app that uses the Endpoint Security API.
I need to mute a few processes like: my own process, xcode, etc' ...
However, if the muted processes create child processes, I want these processes to be muted as well. The full process tree under muted processes should be muted.
How can that be done?
Cant see in docs and can't find an example.
If it can't be done, whats the closest thing to that I can implement.
Thanks!
I have an app that uses Endpoint security.
I have 1 client that registered many AUTH and NOTIFY event types.
When I I recive an Endpoint Security message (event) and my handler is called. Which thread does it use?
If I have 1 client will it always just use the same 1 thread?
If not, can it ever happen that I register 1 client, and he will handle more then 1 event in the same time? regardless of the event type or any thing else
Hello!
I am using the eventDidReachThreshold callback in the DeviceActivityMonitor in order to shield a target app after the user has spend x amount of time on it (e.g. x = 5 minutes).
Many times this works fine, and I can trigger my shield after the specified threshold has been met.
However sometimes, when they leave the target app before the threshold has been reached, the eventDidReachThreshold callback gets called randomly while they are doing something else on their phone (e.g. using a different app, on the Home Screen, phone locked…).
From my perspective this does not make sense, since they are not actively spending time on the target app, and that time should not be counted towards the target app’s threshold.
And it is also very confusing for the users because they will then find a blocked target app even though they haven’t used their time budget completely.
This is not related to the intervalDidStart / intervalDidEnd callbacks, because they are not correlating with the timing of when the eventDidReachThreshold callback is called unexpectedly.
Any ideas what this could be related to?
My organization is using mutual TLS authentication for HTTPS, with PIV cards storing the certs. We observe that some OS X devices send only the leaf certs when establishing the mTLS connection, whereas others send the entire chain. We cannot validate the leaf cert without the intermediate cert, so those clients are rejected.
What drives the decision whether to send the whole chain, vs the leaf cert only?
For more details, and some things we observed.
The PIV cards are US DoD CAC cards: https://www.cac.mil/common-access-card/
The client cert chain on the card looks like this:
Leaf client cert, CN=LastName.Name
Intermediate cert, CN=DOD ID CA-70
"Root" cert, CN=DoD Root CA 6
through 8.: Additional interoperability certs.
Our system is set up to trust the "root" cert CN=DoD Root CA 6.
Neither the leaf cert, nor other certs in the chain are trusted by Apple Keychain Trust Store by default.
We find that most laptops will send the entire chain, 1 through 8, when establishing the mTLS connection with our servers. This allows us to validate them correctly.
On a subset of OS X devices, Google Chrome will only send the leaf chain. This happens even when we use exact same PIV card, and exact same PIV reader as on working laptops. Safari will not send any cert at all.
We found that if we explicitly add the CN=DoD Root CA 6 to the Apple Trust Store, Google Chrome and Safari will start sending a short chain, containing only certs 1 through 3. This allows the server to validate them. When we remove it from Trust Store, Chrome is back to sending only leaf, but Safari will not even send the leaf.
Again, this only happens on some laptops; on most of the laptops, both Safari and Google Chrome will send the entire chain, regardless of whatever is set up in Trust Store.
My suspicion is that for some reason, on those laptops, Safari will not send the client certs that OS X doesn't trust. This makes sense, but this is not the behavior we want. We want the same behavior on the working laptops, which is to send the whole chain.
All of our laptops are on OS X 14.4