Prioritize 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

How secure is the communication between iOS app and its safari mobile extensions
Can someone share how secure is the communication between iOS app and its safari mobile extension. Is it encrypted? Are there any references to best practices to follow? If a user has opened multiple tabs and has multiple extensions can there be security issues during their communication like one extension able to read other extensions memory?
0
0
452
Mar ’24
AppAttest attestKey returns invalid key error
Dear Experts, I have App Attest deployed in an app that is currently in TestFlight. Its works OK most of the time. For one particular user, however, attestKey fails with DCErrorInvalidKey for a new key that it has just created. I have some insight into what the app is doing because I send diagnostics to the server. It seems that for this user, the sequence of events is: Initially the app has no key ID saved. The user initiates an action that requires App Attest-signed communication with my server. The app calls generateKey which seems to succeed. The app fetches a challenge from the server. The app calls attestKey. attestKey returns DCErrorInvalidKey. The app doesn't save the key ID persistently, so next time the same thing happens. attestKey really shouldn't fail with the invalid key error for a key that it has just created, should it? What could be going on here?
6
2
1.2k
Mar ’24
Purposely trigger XProtect detectors?
I have an Endpoint system extension that, in theory, receives XProtect alerts. I regularly see XProtectPluginService starting programs like XProtecteRemediatorSheepSwap on my Mac. I would love to be able to put one or more files/bundles on my Mac that triggers the detectors, so I can see the alerts go from the Endpoint system extension through to the UI. Does Apple have or recommend a way (short of being infected) for triggering the XProtect detectors for testing?
2
0
681
Mar ’24
Support on Apple Privacy Manifest
As per the https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_data_use_in_privacy_manifests Mentions that Third-party SDKs need to provide their own privacy manifest files. What about the SDKs which are in-house? Meaning if the application contains the SDKs which are developer within the same company as the application would be treated as Third-party SDKs?
1
0
549
Mar ’24
Keychain ACLs and evaluatedPolicyDomainState
If on iOS an app protects a keychain item with an access control list that specifies .biometryCurrentSet in its SecAccessControlCreateFlags the app loses access to the item if the set of currently enrolled fingers (for Touch ID) or the currently enrolled user (for Face ID) changes - which corresponds to a change of the evaluatedPolicyDomainState. We have users reporting loss of such items even though - as they assure us - they have not touched (no pun intended) anything under "[Touch|Face] ID & Code" in Preferences.app. Is there another reason why an app may lose access to such items?
0
0
382
Mar ’24
Investigating hard-to-reproduce keychain problems
Keychain is a bit of a ‘call driver’ for DTS. I’ve sent instructions like this to many developers over the years. Today I decided to write it down for everyone’s benefit. If you have questions or comments, put them in a new thread here on DevForums. Tag it with Security so that I see it. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Investigating hard-to-reproduce keychain problems SecItem is the primary API for the keychain on all Apple platforms. If you’re getting started with that API, I have two DevForums posts that you’ll find useful: SecItem: Fundamentals SecItem: Pitfalls and Best Practices Also, if you’re on macOS, make sure to read TN3137 On Mac keychain APIs and implementations. Every now and again folks encounter a hard-to-reproduce keychain problem. For example, you might have code that works most of the time but fails for some users in the field. This failure might be seen regularly by some users, or it might happen sporadically across all your users. Problems like this are often caused by a bug in the system itself, but the SecItem API is sufficiently tricky that I’ve seen cases of this where the actual problem was a bug in the developer’s code. This post outlines a process for investigating such problems. I’ve helped a number of developers use it to good effect, and I figured I should share it for the enjoyment of all (hey hey!). This process depends on the system log. If you’re not best friends with the system log, you should be! See Your Friend the System Log. This process is a special case of the process I describe in Using a Sysdiagnose Log to Debug a Hard-to-Reproduce Problem. Read that before continuing. Unwrap the wrapper Many developers use a wrapper around the SecItem API. Such wrappers make it hard to investigate problems like this. For example, you might call a wrapper routine that returns a password string or nil if there’s a failure. That means you can’t distinguish between an expected nil, where the password hasn’t been saved yet, or a weird error. If you need to debug a hard-to-reproduce keychain problem, look through the wrapper to find the calls to Apple’s SecItem APIs. It’s fine to leave your wrapper in place, but do this debugging at the SecItem level. Add before and after log points The basic strategy here is: Add a log point before the call to the SecItem API, including the parameters that you’ll pass in. Add a log point after the call to the SecItem API, including the returned error code and any response you got. This is trickier than it might seem due to the way that the SecItem API is structured. Consider this example: func copyAccountPassword(_ userName: String) -> String? { var copyResult: CFTypeRef? = nil let err = SecItemCopyMatching([ kSecClass: kSecClassGenericPassword, kSecAttrService: "WaffleVarnish", kSecAttrAccount: userName, kSecReturnData: true, ] as NSDictionary, &copyResult) guard err == errSecSuccess, let result = String(data: copyResult! as! Data, encoding: .utf8) else { return nil } return result } There are a bunch of issues here: The query dictionary is created inline, so it’s not easy to log it. The query dictionary contains the kSecAttrAccount property, which is likely to hold private data. The query can fail, leaving copyResult set to nil. The query can work but return invalid data. In this case the function will return nil but there’s no error. The password is obviously private data. WARNING Be careful when logging keychain data. The whole point of the keychain is to protect the user’s secrets. It would be bad to then go and log those secrets to the system log. Here’s an updated version of that routine: func copyAccountPasswordWithLogging(_ userName: String) -> String? { let query = [ kSecClass: kSecClassGenericPassword, kSecAttrService: "WaffleVarnish", kSecAttrAccount: userName, kSecReturnData: true, ] as NSDictionary var copyResult: CFTypeRef? = nil log.log("will copy account password, query: \(query)") let err = SecItemCopyMatching(query, &copyResult) guard err == errSecSuccess else { log.log("did not copy account password, err: \(err)") return nil } guard let result = String(data: copyResult! as! Data, encoding: .utf8) else { log.log("did not copy account password, malformed") return nil } log.log("did copy account password") return result } This example assumes that log is a value of type Logger. Redact private data This new code isn’t perfect: The query value is considered private data and not recorded in the log. It logs nothing about the resulting password. Addressing the second problem is a challenge. You could do something creative like log a salted hash of the password but, honestly, I think it’s best to err on the side of caution here. You might try to fix the first problem with code like this: !!! DO NOT DO THIS !!! log.log("will copy account password, query: \(query, privacy: .public)") !!! DO NOT DO THIS !!! However, that’s problematic because it logs the account value (kSecAttrAccount) when it should be redacted. What you do about this depends on the scope of your deployment: If you’re targeting an internal test harness, you might choose to leave it as is. The machines on the test harness don’t have any truly private data. If this code is going to be used by actual humans, you must further redact your logging. For example, you might write a helper like this: func redactedQuery(_ query: NSDictionary) -> String { let query = query.mutableCopy() as! NSMutableDictionary if query.object(forKey: kSecAttrAccount as NSString) != nil { query.setObject("REDACTED", forKey: kSecAttrAccount as NSString) } return "\(query)" } You’ll have to customise this code for your specific use case. For example, your code might put information that’s not private into kSecAttrAccount — in many of my projects, I use a fixed string for this — and so redacting that might be pointless. OTOH, your code might put private information into other properties. If you call a SecItem API that returns a dictionary, you’ll need a similar redactedResponse(_:) routine for that response. Test your logging The next step is to test your logging. Make sure that the stuff you want logged is logged and the stuff you don’t want logged is not. Test outside of Xcode, because Xcode automatically captures private data. Look in the log When you get a sysdiagnose log back from a user having this problem, unpack and open the system log snapshot. Find all the log entry pairs created by your before and after log points. Then look for the most recent one that illustrates the problem you’re investigating. To learn more about the cause of this problem, look for other log entries of interest between those two points. When looking at keychain-related log entries, keep in mind that most of the Security framework is open source. If you’re curious what a log entry means, search the source to see the context. Note Darwin open source won’t always exactly match the source in the corresponding OS version. Also, the Security framework is only part of the story here, and some other subsystems that are relevant to the keychain aren’t open source. However, my experience is that looking at the source is super useful. If you find that log entries are missing, remember that the system log purges older log entries to make room for newer ones. That’s why it’s important to take your sysdiagnose as soon as possible after encountering the problem. If you escalate this problem to Apple — via a bug report, a DTS tech support incident, or whatever — make sure to include: Your sysdiagnose log The exact timestamps of your before and after log entries We may not need this level of information, but in many cases it really helps.
0
0
509
Mar ’24
Is there a reason why the colors are displayed differently in the mail related to Privacy Manifest?
This is the mail I received from Apple while testing. If you look at it, it shows that there are two items that are problematic. As you can see, "ITMS-91053: Missing API decimation" shows the same problem in both, but the colors are displayed differently. (Purple, Gray) There were four problems in the mail I received while testing more, but all of them received the same color. Is this just a mail error?? Or does the color have a meaning?
1
0
1k
Mar ’24
How do I check if a version of an sdk I am using in my app uses a privacy impacting sdk?
I am assuming that even if the app i am using is not listed in the ios list of privacy impacting sdks, if they use a privacy impacting sdk in their sdk, then my app will be required to get the privacy manifest for that privacy impacting sdk: the rule must (logically!) be transitive. So far apple has not sent any email about the app needing to provide that for any of our sdks. but i am worried that maybe apple has not done the check for us yet, and by the time they do , we will be near deadline to submit an app.
1
0
658
Mar ’24
Create a SecKey from .p8 file
Hi, I am trying to create a secKey from a .p8 file which I will then use to sign some data. I'm targeting an iOS application. I understand I cannot use the p8 key directly with iOS APIs and will have to unwrap the p8 file before I can feed it to SecKeyCreateWithData I'm unsure how to go about doing it though and any help will be appreciated. For context it is the APNS p8 file.
1
0
428
Mar ’24
"Document storage" in privacy settings
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?
0
0
445
Mar ’24
Do App extensions require privacy manifests?
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.
2
2
1.3k
Mar ’24