Prioritize user privacy and data security in your app. Discuss best practices for data handling, user consent, and security measures to protect user information.

All subtopics

Post

Replies

Boosts

Views

Activity

How do I display the "You can choose to quit "AppName" now, or do it on your own later." dialog?
Install and launch a macOS app. At that time, if the app requires permission to record the screen, the following dialog will be displayed from the OS. Grant access to this application in Privacy & Security settings, located in System Settings.   Follow the instructions in this dialog and select "Allow" in the system settings screen. Normally, after "Allow", the following dialog should be displayed from the OS. "AppName" mac may not be able to record the contents of your screen until it is quit. You can choose to quit "AppName" now, or do it on your own later.   But, it does not appear. Why? Is there some setting that needs to be done on the app side?
1
0
117
1w
Ambiguity in Apple docs - Hermes privacy manifest
The list of common 3rd party SDKs that require a privacy list here: https://developer.apple.com/support/third-party-SDK-requirements/ References a "hermes" SDK. There is some ambiguity about whether this references Facebook/meta's hermes JS engine: https://github.com/facebook/hermes Or Imgur's Hermes notification system: https://github.com/Imgur/Hermes A representative from Meta claims that Apple is referring to Imgur's library, despite the branding using a capital H and Apple's list using a lowercase h (see here: https://github.com/react-native-community/discussions-and-proposals/discussions/776). Can someone from Apple please confirm which SDK is concerned ? We wish to avoid app rejections. Thank you
1
1
111
1w
Generating a signature for promotional offers in Objective-c
My requirements are to generate a signature for a promotional offer in the iOS app code (Objective-C), but I'm getting nil every time with the error: 'The operation couldn’t be completed. (OSStatus error -50 - EC private key creation from data failed).' Please refer to my code below and suggest how I can get the signature. The privateKeyPath is a .p8 file saved in the Xcode project's main folder: + (NSString *)generateSignatureWithKeyId:(NSString *)keyId bundleId:(NSString *)bundleId productId:(NSString *)productId offerId:(NSString *)offerId nonce:(NSUUID *)nonce timestamp:(NSTimeInterval)timestamp privateKeyPath:(NSString *)privateKeyPath { // Load the private key NSString *privateKeyString = [NSString stringWithContentsOfFile:privateKeyPath encoding:NSUTF8StringEncoding error:nil]; if (!privateKeyString) { NSLog(@"Failed to load private key"); return nil; } // Remove the header and footer privateKeyString = [privateKeyString stringByReplacingOccurrencesOfString:@"-----BEGIN PRIVATE KEY-----" withString:@""]; privateKeyString = [privateKeyString stringByReplacingOccurrencesOfString:@"\n" withString:@""]; privateKeyString = [privateKeyString stringByReplacingOccurrencesOfString:@"\r" withString:@""]; privateKeyString = [privateKeyString stringByReplacingOccurrencesOfString:@"-----END PRIVATE KEY-----" withString:@""]; // Convert to NSData NSData *privateKeyData = [[NSData alloc] initWithBase64EncodedString:privateKeyString options:NSDataBase64DecodingIgnoreUnknownCharacters]; NSLog(@"NSDATA private key: %@", [privateKeyData base64EncodedStringWithOptions:0]); if (!privateKeyData) { NSLog(@"Failed to decode private key"); return nil; } // Create the payload string NSString *payloadString = [NSString stringWithFormat:@"%@\u2063%@\u2063%@\u2063%@\u2063%@\u2063%@\u2063%.0f", bundleId, keyId, productId, offerId, @"", // appAccountToken is optional, leave empty if not used [nonce UUIDString], timestamp]; NSData *payloadData = [payloadString dataUsingEncoding:NSUTF8StringEncoding]; // Sign the payload NSData *signature = [self signData:payloadData withPrivateKey:privateKeyData]; if (!signature) { NSLog(@"Failed to sign data"); return nil; } // Base64 encode the signature NSString *signatureBase64 = [self base64UrlEncode:signature]; return signatureBase64; } + (NSData *)signData:(NSData *)data withPrivateKey:(NSData *)privateKey { SecKeyRef keyRef = [self createSecKeyRefFromPrivateKeyData:privateKey]; if (!keyRef) { NSLog(@"Failed to create private key reference."); return nil; } size_t sigLen = SecKeyGetBlockSize(keyRef); uint8_t *sig = malloc(sigLen); if (sig == NULL) { NSLog(@"Failed to allocate memory for signature."); return nil; } OSStatus status = SecKeyRawSign(keyRef, kSecPaddingPKCS1, data.bytes, data.length, sig, &sigLen); if (status != errSecSuccess) { NSLog(@"Failed to sign data: %d", (int)status); free(sig); return nil; } return [NSData dataWithBytes:sig length:sigLen]; } + (SecKeyRef)createSecKeyRefFromPrivateKeyData:(NSData *)privateKeyData { NSString *base64EncodedString = [privateKeyData base64EncodedStringWithOptions:0]; SecKeyRef privateKeyRef = NULL; NSDictionary *privateKeyAttr = @{ (id)kSecAttrKeyType: (id)kSecAttrKeyTypeECSECPrimeRandom, (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate, (id)kSecAttrKeySizeInBits: @256, (id)kSecAttrIsPermanent: @NO }; CFErrorRef error = NULL; privateKeyRef = SecKeyCreateWithData((__bridge CFDataRef)privateKeyData, (__bridge CFDictionaryRef)privateKeyAttr, &error); if (error != NULL) { NSString *errorDescription = CFBridgingRelease(CFErrorCopyDescription(error)); NSLog(@"Error creating private key reference: %@", errorDescription); CFRelease(error); privateKeyRef = NULL; } return privateKeyRef; }
2
0
155
1w
Have a Multiplatform app, cannot test my app that uses App Groups properly
Dear Apple Developer Forum community, I have a Multiplatform SwiftUI app that runs on both iOS and macOS. The app is available in the Mac App Store, and I aim to maintain backward compatibility. I use App Groups to synchronize data between the main app, where users configure content, and the widget, which displays this content. The data is stored using SwiftData. With macOS Sequoia now in beta testing, I have encountered a breaking change that affects my app. In macOS Sequoia, apps must use the team identifier number $(TeamIdentifierPrefix) as the prefix for App Groups on macOS. I cannot properly test future versions of my app without instructing my beta testers to turn off System Integrity Protection (SIP). This presents a significant issue for my Multiplatform SwiftUI app. On iOS, the app group identifier must start with group.identifier. Before macOS Sequoia, you could name your app group freely, and testing with TestFlight and publishing to the App Store was straightforward. Now, however, testing an app intended for the App Store is complicated by this rule. On macOS, you must use $(TeamIdentifierPrefix) to bypass this rule and allow for widgets to be tested and allow for synchronization between SwiftData. While on iOS, this approach is not allowed as the App Group becomes considered invalid. Additionally, this annoying popup appears every time a beta tester tries to open the app if they have SIP turned on: Instead of prompting for the app extensions, it rejects it. Rejecting this popup also prevents the main SwiftData app from opening. I am unsure how to proceed. If I want to test widgets (which is a primary focus of the app), I must use macOS Sequoia. I am particularly concerned about the implications if I decide to stop supporting macOS Sonoma in the future. Thank you in advance, LocalWE
3
1
246
1w
Documentation of Frameworks that throw ObjC Exceptions?
I recently discovered that CryptokenKit (TKSmartCard.transmit) throws an ObjC exception, and thus crashes a Swift app using TKSmartCard (absent an ObjC wrapper to handle the Objc exception explicitly). That was surprising, as there was no documentation indicating that TKSmartCard needs to be wrapped in ObjC instead being used directly from Swift. (See https://developer.apple.com/documentation/cryptotokenkit/tksmartcard/1390161-transmit) - the exception is a NSInternalInconsistencyException, which is thrown when certain codepaths are executed in a certain sequence (which indeed, leaves a TKSmartCard in an inconsistent state). Is there a list of Frameworks that throw ObjC exceptions (and therefore need special handling by Swift when invoking methods/functions)?
3
0
180
1w
Can Message Filter Extension use configured Shared Web Credentials for auth'd calls?
We've created a Message Filter Extension that relies on the network action workflow of Message Filter Extensions (ILMessageFilterExtension). Has anyone applied authentication to these calls? It works great when being called un-authenticated, but the logic behind this API costs us money, and we'd like to rate-limit it by the client to avoid someone DDOs'ing the exposed API and racking up our bill. We've followed https://developer.apple.com/documentation/sms_and_call_reporting/sms_and_mms_message_filtering/creating_a_message_filter_app_extension and set up a Shared Web Credential (both webcredential and messagefilter associated domains). Still, our calls never have the created and verified credentials forwarded to our service with the REST API call. Have any thoughts on how to apply a shared web credential to those delegated calls?
1
0
204
1w
Unable to connect to Wifi AP with AccessorySetupKit
Hi, I'm trying to connect to a Wifi access point with the new AccessorySetupKit framework. At first i thought that ASK would establish the connection to the access point but then it was mentioned in the session that I need to do that myself with NEHotspotConfigurationManager. I tried to do that but every time I get this error: NEHotspotConfigurationErrorDomain Code=17 "system denied configuration of the accessory network." My AP is just a small ESP32 but I get the same results with any other AP. Looking at the logs in Console.app for my device, I see some interesting logs such as these: Subsystem: com.apple.AccessorySetup, Category: ASAccessorySession Received event: DADeviceEvent: type DeviceChangedDADeviceEvent: device DADevice: ID D0A7B5FB-6800-4B73-9DC4-697DDE791D2B, name 'Printer Emulator', flags AccessorySetup, SSID 'ESP32-AP', type Hi-Fi Speaker, { DADeviceAppAccessInfo: com.criboe.GBPE, ID D0A7B5FB-6800-4B73-9DC4-697DDE791D2B, state Authorized, < WiFi >, Time 2024-07-10-11:16:40.389, disConfig asID 6CC66EF2-9D12-4071-92E4-7038D741D5E5, btSv [], com.criboe.GBPE, flags 0x8 < RenameSSID >, hSPs [ "ESP32" ] } Subsystem: com.apple.DeviceAccess, Category: DADaemonServer [WiFi] profile not found for SSID = 'ESP32-AP' [WiFi] profile not found for SSID = 'ESP32-AP' [WiFi] profile not found for SSID = 'ESP32-AP' ...and many more... Subsystem: --, Category: (wifid) WiFiManagerAddNetworkAsync: Request to add network with content: ESP32-AP: isHidden=0, isEAP=0, isSAE=0, isWPA=0, isWEP=0, WAPI=0, type=0, enabled=(null), saveData=(null), responsiveness=(null) ((null)) isHome=Unknown, isForceFixed=0, transitionDisabledFlags=(null), foundNanIe=0, isPH=0, isPublicAirPlayNetwork=0, is6EDisabled=0, hs20=0, Channel=0 WiFiManagerAddNetworkAsync: adding ssid='ESP32-AP' bundleId='com.criboe.GBPE' appName='Camera Boy' originator='3rd Party' HS20=0 __GetNetworkWithSameSsid: network ESP32-AP not found WiFiManagerAddNetworkAsync: 'com.criboe.GBPE' is authorized to join 'ESP32-AP: isHidden=0, isEAP=0, isSAE=0, isWPA=0, isWEP=0, WAPI=0, type=0, enabled=(null), saveData=(null), responsiveness=(null) ((null)) isHome=Unknown, isForceFixed=0, transitionDisabledFlags=(null), foundNanIe=0, isPH=0, isPublicAirPlayNetwork=0, is6EDisabled=0, hs20=0, Channel=0' What is weird is that if I don't use ASK to first find my accessory and simply call NEHotspotConfigurationManager.shared.apply(_: ) I can connect to the AP just fine. Any suggestions to what might be wrong here?
1
0
213
1w
Account Authentication Modification Extension on iOS 18
We currently have an Account Authentication Modification Extension in our iOS App so that users can update their passwords directly from within the Passwords section in the iOS Settings App. On iOS 18 beta3 the extension is not executed from the new Passwords app. Instead the URL associated with the credentials is opened when choosing to change a password. Will it still be possible to integrate with the new Passwords app or is this no longer supported? https://developer.apple.com/wwdc24/10125 only mentions https://example.com/.well-known/change-password Also, can we provide the information to the Passwords app that our service does not support verification codes? So that the "set up verification code" option is not displayed for our website in the Passwords app.
0
0
157
1w
CGDisplayStream API hangs on MacOS15 for same name process
Hi, recently some users of my app upgrade MacOS to 15, and encounter hang when trying to get screen capture permission. After looking into this issue, I find out a repoducible way. If two processes of a same program both call CGDisplayStreamCreate/CGDisplayImageCreate API, the later one will hang(No need to be at almost same time). Here are my demo codes. #import <AVFoundation/AVFoundation.h> #import <CoreGraphics/CoreGraphics.h> #import <Foundation/Foundation.h> int main(int argc, const char *argv[]) { @autoreleasepool { CGDirectDisplayID displayID = CGMainDisplayID(); CGDisplayStreamRef stream = CGDisplayStreamCreate( displayID, 1, 1, kCVPixelFormatType_32BGRA, nil, ^(CGDisplayStreamFrameStatus status, uint64_t displayTime, IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef){ }); if (!stream) { NSLog(@"Failed to create display stream!"); return 1; } else { NSLog(@"Create display stream success!"); CFRelease(stream); } } sleep(10); return 0; } The call of sleep is just to ensure I can run a second process of this program before the first one ends. It turns out that the first process checks the permission correctly and sleeps successfully. However the second process won't be able to print anything because it hangs when calling CGDisplayStreamCreate. Here is the output of sample: Call graph: 2546 Thread_1315735 DispatchQueue_1: com.apple.main-thread (serial) + 2546 start (in dyld) + 2840 [0x196f8f274] + 2546 main (in testapp) + 76 [0x100ef7e38] + 2546 SLDisplayStreamCreate (in SkyLight) + 316 [0x19d38163c] + 2546 SLSDisplayStreamCreateProxying (in ScreenCaptureKit) + 816 [0x231e2d614] + 2546 _dispatch_semaphore_wait_slow (in libdispatch.dylib) + 76 [0x19715e278] + 2546 _dispatch_sema4_timedwait (in libdispatch.dylib) + 64 [0x19715dc78] + 2546 semaphore_timedwait_trap (in libsystem_kernel.dylib) + 8 [0x1972ceda8] 2546 Thread_1315737 2546 start_wqthread (in libsystem_pthread.dylib) + 8 [0x19730b0f0] 2546 _pthread_wqthread (in libsystem_pthread.dylib) + 364 [0x19730c424] 2546 __workq_kernreturn (in libsystem_kernel.dylib) + 8 [0x1972d0a64] If I copy the program and run two different programs, the second program won't hang. This issue doesn't happen on MacOS early version. Can anybody help?
0
0
141
1w
Use/Request Touch ID without Authentication Prompt
On macOS, in the Apple Passwords app (currently inside Settings but soon to be it's own full fledged app in Sequoia) the user is presented with a screen requesting that they touch the fingerprint reader (see attached). If we'd like to do something similar, e.g. unlock some sensitive/secure part of our app, by requesting the user touch the Touch ID sensor, but without doing the whole system prompt (LAContext.evaluatePolicy()), how can we do that? Is that possible for mere mortal developers, and if not, why not?
2
0
184
1w
Could not mount root filesystem after disable SIP
I'm using intel macOS 14.5. I'm trying to use Kernel Debug Kit, so I disabled SIP protection via csrutil disable. To locate development version of kernel in Kernel directory, I have to use the command sudo mount -uw /. However, it produces error as following: mount_apfs: volume could not be mounted: Permission denied mount: / failed with 66 How to solve the problem? Thank you for your attention.
1
0
93
1w
Which message should monitor to replace by Endpoint Security
I'm using the ES framework to control files created by handling the event ES_EVENT_TYPE_AUTH_CREATE, but when a file is created by replacing the same name file, ES_EVENT_TYPE_AUTH_CREATE won't be reported. I've searched and tried the event ES_EVENT_TYPE_AUTH_EXCHANGEDATA, but it didn't work. Which event should I monitor for 'creating a file' by replacing a file with the same name?
1
0
155
1w
App flagged with bypassed SSL Pinning during Mobile App Penetration Test
Recently our app went through a series of Mobile App Penetration Test (MAPT), and was flagged with bypassed SSL Pinning (https://cwe.mitre.org/data/definitions/693.html). The tester is using Frida and is able to attach to SSL_CTX_set_custom_verify() from libboringssl.dylib, as shown in this script (https://codeshare.frida.re/@federicodotta/ios13-pinning-bypass/). As per my research, though I'm not absolutely sure, I see that boringSSL was added since iOS 11 (https://developer.apple.com/forums/thread/88387) and (https://github.com/firebase/firebase-ios-sdk/issues/314). I would like to check if there is anyway around this, as I am using TrustKit (https://cocoapods.org/pods/TrustKit), and I realised many other pods also tag on SSL_CTX_set_custom_verify() for SSL Pinning. As our app requires SSL Pinning, and a resolution to this issue, I would like to ask if there is any solution, whether it being a recommended pod/library, or a native solution (preferred) to do SSL Certificate Pinning. Thank you.
5
0
201
1w
Check if a binary or script is executable
In one of our apps (not sandboxed) the user can choose a file that matches one of the following UTTypes using an NSOpenPanel: UTTypeApplicationBundle UTTypeUnixExecutable UTTypeShellScript The selected file will then be launched under certain circumstances. This works pretty well but from time to time we see internal support tickets where people complain because the selected file is not executed. This only affects files of type UTTypeUnixExecutable and UTTypeShellScript for which the Unix permissions are incorrect. They are therefore not executable. I would now like to check in the app whether the selected file is executable. With app bundles this works without any problems with isExecutableFileAtPath:, but with the other file types this does not work. What is the recommended way to test this for the other files? Is there a better way than checking the POSIX permissions (and owner/group)? Thanks.
3
0
188
1w
NSUpdateSecurityPolicy don't work or how to request App Managment permission?
I have two MAUI Mac Catalyst apps. According to this guide https://learn.microsoft.com/en-us/dotnet/maui/mac-catalyst/deployment/publish-outside-app-store?view=net-maui-8.0#publish-using-the-command-line I created certificates, signed Release versions of applications, packed them with pkgbuild and productbuild which I also signed with created certificate They are both signed with same Code Signing key, have same team id. I had set up NSUpdateSecurityPolicy https://developer.apple.com/documentation/bundleresources/information_property_list/nsupdatesecuritypolicy like this: Using codesign -dv I cheked that updater, old and new versions of app share same Team Id and have correct bundle identifiers After update, updater wants to overwrite old app contents, but it always receives UnathorizedAccessException when touching any file located in application If my updater app has "App Managment" or "Full disk access" permission in System settings, everything works fine, but user needs to set up it manualy, that is not comfortable, so how can I request this permission? Also according to what I know, application don't need this permission if it's Team ID set up in NSUpdateSecurityPolicy Maybe I incorrectly set up NSUpdateSecurityPolicy, but I can't notice anything wrong. Also, can it be because I overwrite application using MAUI and C#? Thanks a lot for any answer!
2
0
232
1w
App Attest Server Validations
I'm following the attestation object validation guide to check my attestation server validations, but having a different output of that it's expected in the documentation. Everything goes well until the step 2, where it's created the SHA256 hash of the one-time challenge, then this hash it's appended to the end of the authenticator data from the decoded attestation object. Here the generated client data hash is different from the one in the documentation, which also causes a different nonce value. Full implementation at Go Playground: https://go.dev/play/p/DpL_H3L8yWV // generate the SHA256 hash of the one-time challenge challengeHash := sha256.Sum256([]byte(serverChallenge)) // append the one-time challenge hash to the end of the authenticator data clientDataHash := append([]byte(att.AuthData), challengeHash[:]...) // create a SHA256 hash of the composite item to create nonce nonce := sha256.Sum256(clientDataHash) Then I noticed that if the one-time challenge value it's just appended to the end of the authenticator data, the value it's correctly according to the documentation. Full implementation at Go Playground: https://go.dev/play/p/qqN97SevJAB // append the one-time challenge byte array to the end of the authenticator data // this time not generating the SHA256 hash of the one-time challenge clientDataHash := append([]byte(att.AuthData), []byte(serverChallenge)...) // create a SHA256 hash of the composite item to create nonce nonce := sha256.Sum256(clientDataHash) My question is which of the implementations is correct, because if I didn't get it wrong it should be the first one and we would have an error in the documentation.
1
1
256
2w