Security

RSS for tag

Secure the data your app manages and control access to your app using the Security framework.

Posts under Security tag

139 Posts

Post

Replies

Boosts

Views

Activity

Capturing screen buffer at macOS Login Window with ScreenCaptureKit and PrivilegedHelper
I am developing a remote support tool for macOS. While we have successfully implemented a Privileged Helper Tool and LaunchDaemon architecture that works within an active Aqua session, we have observed a total failure to capture the screen buffer or receive input at the macOS Login Window. Our observation of competitor software (AnyDesk, TeamViewer) shows they maintain graphical continuity through logout/restart. We are seeking the official architectural path to replicate this system-level access. Current Technical Implementation Architecture: A root-level LaunchDaemon manages the persistent network connection. A PrivilegedHelperTool (installed in /Library/PrivilegedHelperTools/) is used for elevated tasks. Environment: Tested on macOS 14.x (Sonoma) and macOS 15.x (Sequoia) on Apple Silicon. Capture Methods: We have implemented ScreenCaptureKit (SCK) as the primary engine and CGDisplayCreateImage as a fallback. Binary Status: All components are signed with a Developer ID and have been successfully Notarized. Observed Behavior & Blockers The "Aqua" Success: Within a logged-in user session, our CGI correctly identifies Display IDs and initializes the capture stream. Remote control is fully functional. The "Pre-Login" Failure: When the Mac is at the Login Window (no user logged in), the following occurs: The Daemon remains active, but the screen capture buffer returns NULL or an empty frame. ScreenCaptureKit fails to initialize, citing a lack of graphical context. No TCC (Transparency, Consent, and Control) prompt can appear because no user session exists. The "Bootstrap" Observation: We have identified that the loginwindow process exists in a restricted Mach bootstrap namespace that our Daemon (running in the System domain) cannot natively bridge. Comparative Analysis (Competitor Benchmarking) We have analyzed established remote desktop solutions like AnyDesk and Jump Desktop to understand their success at the login screen. Our findings suggest: Dual-Context Execution: They appear to use a Global LaunchAgent with LimitLoadToSessionType = ["LoginWindow"]. This allows a child process to run as root inside the login window’s graphical domain. Specialized Entitlements: These apps have migrated to the com.apple.developer.persistent-content-capture entitlement. This restricted capability allows them to bypass the weekly/monthly TCC re-authorization prompts and function in unattended scenarios where a user cannot click "Allow." Questions Entitlement Requirement: Is the persistent-content-capture entitlement the only supported way for a third-party app to capture the LoginWindow buffer without manual user intervention? LaunchAgent Strategy: To gain a graphical context at the login screen, is it recommended to load a specialized agent into the loginwindow domain via launchctl bootstrap loginwindow ...? ScreenCaptureKit vs. Legacy: Does ScreenCaptureKit officially support the LoginWindow session, or does it require an active Aqua session to initialize? MDM Bypass: For Enterprise environments, can a Privacy Preferences Policy Control (PPPC) payload grant "Screen Recording" to a non-entitled Daemon specifically for the login window context?
1
0
444
Jan ’26
Support for Additional Key Exchange Groups (SecP256r1MLKEM768 and SecP384r1MLKEM1024) on iOS 26 for WKWebView and NSURLSession
As part of iOS 26, we get X25519MLKEM768 key exchange group support, but SecP256r1MLKEM768 and SecP384r1MLKEM1024 are not supported. Is there any way to enable these key exchange groups on iOS 26? We need them for WKWebView and NSURLSession. STEPS TO REPRODUCE On iOS 26, connect to the PQC server using Safari. The key exchange group is limited to X25519MLKEM768.
2
0
211
Feb ’26
App Management permission cannot be given to non-bundled apps
We are using a java program as an installer for a software suite. This program is bundled inside a signed and notarized Mac app, but it uses the system installed Java (from env). For installing software, it requires the App Management permission (currently under System Settings › Privacy & Security › App Management). Since the program runs via the system provided Java executable, that one is the executable, that needs said permission. In the past, it was possible to add java to said permissions list. With macOS 26.2 it is no longer possible. I think, this change happened with 26.2. It was definitely still working with macOS 15 (I can reproduce it there), and I am confident, that it also still worked under 26.1. In Console.app I can see errors like this one /AppleInternal/Library/BuildRoots/4~CCKzugBjdyGA3WHu9ip90KmiFMk4I5oJfOTbSBk/Library/Caches/com.apple.xbs/Sources/SecurityPref/Extension/Privacy/TCC+PrivacyServicesProvider.swift:227 add(record:to:) No bundle or no bundle ID found for record TCCRecord(identifier: "/opt/homebrew/Cellar/sdkman-cli/5.19.0/libexec/candidates/java/11.0.29-tem/bin/rmic", identifierType: SecurityPrivacyExtension.TCCIdentifierType.path, access: SecurityPrivacyExtension.TCCAccess.full, managed: false, allowStandardUserToSetSystemService: false, subjectIdentityBundleIdentifier: nil, indirectObjectIdentityBundleIdentifier: nil, indirectObjectIdentityFileProviderIdentifier: nil, tccAuthorization: <OS_tcc_authorization_record: 0xa97d0ba80>) This is reproducible for various different Java installations. I can also not add Java to the other permissions that I tried. Since Java is not installed in a bundled app but instead as a UNIX executable in a bin-folder, the error No bundle or no bundle ID found for record makes sense. I expect this to also affect other use cases where programs are provided as UNIX executables such as Python or C-Compilers like g++. While it is possible to bundle an entire JRE inside each app, we intentionally chose not to as this massively increases app size. If this issue is not resolved or a workaround can be found, this is the only option that remains for us. I am however worried that there are other use cases where this is not an option.
1
0
162
Jan ’26
Signed app can't be verified
I've signed an app, zipped it, and uploaded it to github. When I download it on another Mac, I get "it can't be opened because it could not be verified for malware". But on that computer, I can verify it with codesign, and it appears to be correct (as far as I can tell). I can copy/paste the app from my other Mac, and that copy will run without problem. sys_policy, however, gives: Notary Ticket Missing File: ReView.app Severity: Fatal Full Error: A Notarization ticket is not stapled to this application. Type: Distribution Error This is the same for the copy that runs, and the copy that doesn't. The difference between them appears to be a quarantine xattr. I can delete this, and the app launches without incident. Is this expected? Why should a signed app be quarantined just because it's been downloaded? The whole point of paying the fee is to avoid the security obstacles...! ;-)
3
0
882
Feb ’26
App Store Requirements: SSL Certificates for Home Raspberry Pi Servers – Practical Solutions?
Hello, A customer has requested the development of a home assistance app to be published on the App Store. The app will connect to a server running locally at the end user's home, for example on a Raspberry Pi. Users would enter the IP address or hostname of their personal server into the app. A strict requirement is that, for data protection reasons, there must not be any proxy server. The app should only communicate directly with the local server (e.g., Raspberry Pi). We are able to solve technical challenges such as DNS, dynamic IP, and port forwarding, router configuration. However, I'm concerned about Apple's requirement that the endpoint – in this case, the Raspberry Pi at the user's home – must not use self-signed SSL certificates. While it may be technically possible to secure the home server with a certificate provider like Let's Encrypt, it is unrealistic to expect a typical user with no technical training to accomplish this setup independently. Is there a recommended solution to this problem, particularly in the context of IoT devices and apps? Any advice or experiences would be deeply appreciated.
1
0
124
Jan ’26
Does accessing multiple Keychain items with .userPresence force multiple biometric prompts despite reuse duration?
Hi everyone, I'm working on an app that stores multiple secrets in the Keychain, each protected with .userPresence. My goal is to authenticate the user once via FaceID/TouchID and then read multiple Keychain items without triggering subsequent prompts. I am reusing the same LAContext instance for these operations, and I have set: context.touchIDAuthenticationAllowableReuseDuration = LATouchIDAuthenticationMaximumAllowableReuseDuration However, I'm observing that every single SecItemCopyMatching call triggers a new FaceID/TouchID prompt, even if they happen within seconds of each other using the exact same context. Here is a simplified flow of what I'm doing: Create a LAContext. Set touchIDAuthenticationAllowableReuseDuration to max. Perform a query (SecItemCopyMatching) for Item A, passing [kSecUseAuthenticationContext: context]. Result: System prompts for FaceID. Success. Immediately perform a query (SecItemCopyMatching) for Item B, passing the same [kSecUseAuthenticationContext: context]. Result: System prompts for FaceID again. My question is: Does the .userPresence access control flag inherently force a new user interaction for every Keychain access, regardless of the LAContext reuse duration? Is allowableReuseDuration only applicable for LAContext.evaluatePolicy calls and not for SecItem queries? If so, is there a recommended pattern for "unlocking" a group of Keychain items with a single biometric prompt? Environment: iOS 17+, Swift. Thanks!
3
0
569
Jan ’26
Limit access for a file/folder to a given application
So I'm aware that Apple can designate a folder as a "data vault", and access to that folder is limited to applications that have a specific entitlement. I was wondering if there was an equivalent (or the same, I'm not fussy :) feature available to third parties, even if only during the app-store submission ? To avoid the X-Y problem, what I want to do is have a launch agent with access to a SQLite database, and I want only that launch agent to have access. Any reads of the database will have to be done through an XPC call from the main user-facing application. I want to store private data into that database, and I don't want there to be any way for any other application to read it. If there's a way to do that without data-vaults I'm all ears :) I'm not sure if this is really the right place, perhaps the core-os forum would be better, but since the Apple solution is gate-kept by entitlements, I thought I'd start here :)
5
0
238
Jan ’26
Hardware Memory Tag (MIE) enforcement outside of debugger
(Xcode 26.2, iPhone 17 Pro) I can't seem to get hardware tag checks to work in an app launched without the special "Hardware Memory Tagging" diagnostics. In other words, I have been unable to reproduce the crash example at 6:40 in Apple's video "Secure your app with Memory Integrity Enforcement". When I write a heap overflow or a UAF, it is picked up perfectly provided I enable the "Hardware Memory Tagging" feature under Scheme Diagnostics. If I instead add the Enhanced Security capability with the memory-tagging related entitlements: I'm seeing distinct memory tags being assigned in pointers returned by malloc (without the capability, this is not the case) Tag mismatches are not being caught or enforced, regardless of soft mode The behaviour is the same whether I launch from Xcode without "Hardware Memory Tagging", or if I launch the app by tapping it on launchpad. In case it was related to debug builds, I also tried creating an ad hoc IPA and it didn't make any difference. I realise there's a wrinkle here that the debugger sets MallocTagAll=1, so possibly it will pick up a wider range of issues. However I would have expected that a straight UAF would be caught. For example, this test code demonstrates that tagging is active but it doesn't crash: #define PTR_TAG(p) ((unsigned)(((uintptr_t)(p) >> 56) & 0xF)) void *p1 = malloc(32); void *p2 = malloc(32); void *p3 = malloc(32); os_log(OS_LOG_DEFAULT, "p1 = %p (tag: %u)\n", p1, PTR_TAG(p1)); os_log(OS_LOG_DEFAULT, "p2 = %p (tag: %u)\n", p2, PTR_TAG(p2)); os_log(OS_LOG_DEFAULT, "p3 = %p (tag: %u)\n", p3, PTR_TAG(p3)); free(p2); void *p2_realloc = malloc(32); os_log(OS_LOG_DEFAULT, "p2 after free+malloc = %p (tag: %u)\n", p2_realloc, PTR_TAG(p2_realloc)); // Is p2_realloc the same address as p2 but different tag? os_log(OS_LOG_DEFAULT, "Same address? %s\n", ((uintptr_t)p2 & 0x00FFFFFFFFFFFFFF) == ((uintptr_t)p2_realloc & 0x00FFFFFFFFFFFFFF) ? "YES" : "NO"); // Now try to use the OLD pointer p2 os_log(OS_LOG_DEFAULT, "Attempting use-after-free via old pointer p2...\n"); volatile char c = *(volatile char *)p2; // Should this crash? os_log(OS_LOG_DEFAULT, "Read succeeded! Value: %d\n", c); Example output: p1 = 0xf00000b71019660 (tag: 15) p2 = 0x200000b711958c0 (tag: 2) p3 = 0x300000b711958e0 (tag: 3) p2 after free+malloc = 0x700000b71019680 (tag: 7) Same address? NO Attempting use-after-free via old pointer p2... Read succeeded! Value: -55 For reference, these are my entitlements. [Dict] [Key] application-identifier [Value] [String] … [Key] com.apple.developer.team-identifier [Value] [String] … [Key] com.apple.security.hardened-process [Value] [Bool] true [Key] com.apple.security.hardened-process.checked-allocations [Value] [Bool] true [Key] com.apple.security.hardened-process.checked-allocations.enable-pure-data [Value] [Bool] true [Key] com.apple.security.hardened-process.dyld-ro [Value] [Bool] true [Key] com.apple.security.hardened-process.enhanced-security-version [Value] [Int] 1 [Key] com.apple.security.hardened-process.hardened-heap [Value] [Bool] true [Key] com.apple.security.hardened-process.platform-restrictions [Value] [Int] 2 [Key] get-task-allow [Value] [Bool] true What do I need to do to make Memory Integrity Enforcement do something outside the debugger?
6
0
1.3k
Feb ’26
Exporting and re-importing ECC keys with file-based keychain
I'm trying to export and re-import a P-256 private key that was originally generated via SecKeyCreateRandomKey(), but I keep running into roadblocks. The key is simply exported via SecItemExport() with format formatWrappedPKCS8, and I did set a password just to be sure. Do note that I must use the file-based keychain, as the data protection keychain requires a restricted entitlement and I'm not going to pay a yearly fee just to securely store some private keys for a personal project. The 7-day limit for unsigned/self-signed binaries isn't feasible either. Here's pretty much everything I could think of trying: Simply using SecItemImport() does import the key, but I cannot set kSecAttrLabel and more importantly: kSecAttrApplicationTag. There just isn't any way to pass these attributes upfront, so it's always imported as Imported Private Key with an empty comment. Keys don't support many attributes to begin with and I need something that's unique to my program but shared across all the relevant key entries, otherwise it's impossible to query for only my program's keys. kSecAttrLabel is already used for something else and is always unique, which really only leaves kSecAttrApplicationTag. I've already accepted that this can be changed via Keychain Access, as this attribute should end up as the entry's comment. At least, that's how it works with SecKeyCreateRandomKey() and SecItemCopyMatching(). I'm trying to get that same behaviour for imports. Running SecItemUpdate() afterwards to set these 2 attributes doesn't work either, as now the kSecAttrApplicationTag is suddenly used for the entry's label instead of the comment. Even setting kSecAttrComment (just to be certain) doesn't change the comment. I think kSecAttrApplicationTag might be a creation-time attribute only, and since SecItemImport() already created a SecKey I will never be able to set this. It likely falls back to updating the label because it needs to target something that is still mutable? Using SecItemImport() with a nil keychain (i.e. create a transient key), then persisting that with SecItemAdd() via kSecValueRef does allow me to set the 2 attributes, but now the ACL is lost. Or more precise: the ACL does seem to exist as any OS prompts do show the label I originally set for the ACL, but in Keychain Access it shows as Allow all applications to access this item. I'm looking to enable Confirm before allowing access and add my own program to the Always allow access by these applications list. Private keys outright being open to all programs is of course not acceptable, and I can indeed access them from other programs without any prompts. Changing the ACL via SecKeychainItemSetAccess() after SecItemAdd() doesn't seem to do anything. It apparently succeeds but nothing changes. I also reopened Keychain Access to make sure it's not a UI "caching" issue. Creating a transient key first, then getting the raw key via SecKeyCopyExternalRepresentation() and passing that to SecItemAdd() via kSecValueData results in The specified attribute does not exist. This error only disappears if I remove almost all of the attributes. I can pass only kSecValueData, kSecClass and kSecAttrApplicationTag, but then I get The specified item already exists in the keychain errors. I found a doc that explains what determines uniqueness, so here are the rest of the attributes I'm using for SecItemAdd(): kSecClass: not mentioned as part of the primary key but still required, otherwise you'll get One or more parameters passed to a function were not valid. kSecAttrLabel: needed for my use case and not part of the primary key either, but as I said this results in The specified attribute does not exist. kSecAttrApplicationLabel: The specified attribute does not exist. As I understand it this should be the SHA1 hash of the public key, passed as Data. Just omitting it would certainly be an option if the other attributes actually worked, but right now I'm passing it to try and construct a truly unique primary key. kSecAttrApplicationTag: The specified item already exists in the keychain. kSecAttrKeySizeInBits: The specified attribute does not exist. kSecAttrEffectiveKeySize: The specified attribute does not exist. kSecAttrKeyClass: The specified attribute does not exist. kSecAttrKeyType: The specified attribute does not exist. It looks like only kSecAttrApplicationTag is accepted, but still ignored for the primary key. Even entering something that is guaranteed to be unique still results in The specified item already exists in the keychain, so I think might actually be targeting literally any key. I decided to create a completely new keychain and import it there (which does succeed), but the key is completely broken. There's no Kind and Usage at the top of Keychain Access and the table view just below it shows symmetric key instead of private. The kSecAttrApplicationTag I'm passing is still being used as the label instead of the comment and there's no ACL. I can't even delete this key because Keychain Access complains that A missing value was detected. It seems like the key doesn't really contain anything unique for its primary key, so it will always match any existing key. Using SecKeyCreateWithData() and then using that key as the kSecValueRef for SecItemAdd() results in A required entitlement isn't present. I also have to add kSecUseDataProtectionKeychain: false to SecItemAdd() (even though that should already be the default) but then I get The specified item is no longer valid. It may have been deleted from the keychain. This occurs even if I decrypt the PKCS8 manually instead of via SecItemImport(), so it's at least not like it's detecting the transient key somehow. No combination of kSecAttrIsPermanent, kSecUseDataProtectionKeychain and kSecUseKeychain on either SecKeyCreateWithData() or SecItemAdd() changes anything. I also tried PKCS12 despite that it always expects an "identity" (key + cert), while I only have (and need) a private key. Exporting as formatPKCS12 and importing it with itemTypeAggregate (or itemTypeUnknown) does import the key, and now it's only missing the kSecAttrApplicationTag as the original label is automatically included in the PKCS12. The outItems parameter contains an empty list though, which sort of makes sense because I'm not importing a full "identity". I can at least target the key by kSecAttrLabel for SecItemUpdate(), but any attempt to update the comment once again changes the label so it's not really any better than before. SecPKCS12Import() doesn't even import anything at all, even though it does return errSecSuccess while also passing kSecImportExportKeychain explicitly. Is there literally no way?
4
0
1.1k
Jan ’26
How do I prevent screenshots using SwiftUI?
Hi Team, How do I prevent screenshots using SwiftUI. I was using this solution on UIKit: extension UIView { func makeSecure() { DispatchQueue.main.async { let protectedView = UIView() self.superview?.addSubview(protectedView) // constraints... let secureView = SecureView() self.superview?.addSubview(secureView) // constraints... secureView.addSecureSubview(self) // constraints... } } } class SecureView: UIView { private lazy var secureField: UIView = { var secureField: UIView = UIView() // ... if let secureContainer = SecureField().secureContainer { secureField = secureContainer } ... return secureField }() required init() { ... } } Is it posible to do the same thing using SwiftUI. Do we have an example? What would you recommend when we work with confidencial information in SwiftUI like bank account information? Thanks in advance!
0
0
207
Dec ’25
Unexpected errSecInteractionNotAllowed (-25308) When Reading Keychain Item with kSecAttrAccessibleAfterFirstUnlock in Background
Hi everyone, I’m encountering an unexpected Keychain behavior in a production environment and would like to confirm whether this is expected or if I’m missing something. In my app, I store a deviceId in the Keychain based on the classic KeychainItemWrapper implementation. I extended it by explicitly setting: kSecAttrAccessible = kSecAttrAccessibleAfterFirstUnlock My understanding is that kSecAttrAccessibleAfterFirstUnlock should allow Keychain access while the app is running in the background, as long as the device has been unlocked at least once after reboot. However, after the app went live, I observed that when the app performs background execution (e.g., triggered by background tasks / silent push), Keychain read attempts intermittently fail with: errSecInteractionNotAllowed (-25308) This seems inconsistent with the documented behavior of kSecAttrAccessibleAfterFirstUnlock. Additional context: The issue never occurs in foreground. The issue does not appear on development devices. User devices are not freshly rebooted when this happens. The Keychain item is created successfully; only background reads fail. Setting the accessibility to kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly produces the same result. Questions: Under what circumstances can kSecAttrAccessibleAfterFirstUnlock still cause a -25308 error? Is there any known restriction when accessing Keychain while the app is running in background execution contexts? Could certain system states (Low Power Mode, Background App Refresh conditions, device lock state, etc.) cause Keychain reads to be blocked unexpectedly? Any insights or similar experiences would be greatly appreciated. Thank you!
3
0
706
Dec ’25
Persistent Tokens for Keychain Unlock in Platform SSO
While working with Platform SSO on macOS, I’m trying to better understand how the system handles cases where a user’s local account password becomes unsynchronized with their Identity Provider (IdP) password—for example, when the device is offline during a password change. My assumption is that macOS may store some form of persistent token during the Platform SSO user registration process (such as a certificate or similar credential), and that this token could allow the system to unlock the user’s login keychain even if the local password no longer matches the IdP password. I’m hoping to get clarification on the following: Does macOS actually use a persistent token to unlock the login keychain when the local account password is out of sync with the IdP password? If so, how is that mechanism designed to work? If such a capability exists, is it something developers can leverage to enable a true passwordless authentication experience at the login window and lock screen (i.e., avoiding the need for a local password fallback)? I’m trying to confirm what macOS officially supports so I can understand whether passwordless login is achievable using the persistent-token approach. Thanks in advance for any clarification.
1
3
294
Dec ’25
KeyChain Sharing with App Extensions
Hi, We are trying to use Apple Security API for KeyChain Services. Using the common App Group : Specifying the common app group in the "kSecAttrAccessGroup" field of the KeyChain query, allowed us to have a shared keychains for different apps (targets) in the app group, but this did not work for extensions. Enabling the KeyChain Sharing capability : We enabled the KeyChain Sharing Ability in the extensions and the app target as well, giving a common KeyChain Access group. Specifying this in the kSecAttrAccessGroup field also did not work. This was done in XCode as we were unable to locate it in the Developer portal in Indentifiers. We tried specifying "$AppIdentifier.KeyChainSharingGroup" in the kSecAttrAccessGroup field , but this did not work as well The error code which we get in all these 3 cases when trying to access the Keychain from the extension is error code 25291 (errSecNotAvailable). The Documentation says this error comes when "No Trust Results are available" and printing the error in xcode using the status says "No keychain is available. The online Documentation says that it is possible to share keychain with extensions, but by far we are unable to do it with the methods suggested. Do we need any special entitlement for this or is there something we are missing while using these APIs? We really appreciate any and all help in solving this issue! Thank you
4
0
309
Dec ’25
Upon trying to archive I got funny errors preventing it
When I try to archive an app in order to submit it to the App Store I receive the following errors I do not know how to fix: error: Framework /Users/fbartolom/Library/Developer/Xcode/DerivedData/Virtual_Tags-apzduassdiglhcapscsllvzbfgid/Build/Intermediates.noindex/ArchiveIntermediates/Virtual Tags/InstallationBuildProductsLocation/Applications/VirtualTags.app/Frameworks/StoreKit.framework did not contain an Info.plist (in target 'VirtualTags' from project 'Virtual Tags') error: Framework /Users/fbartolom/Library/Developer/Xcode/DerivedData/Virtual_Tags-apzduassdiglhcapscsllvzbfgid/Build/Intermediates.noindex/ArchiveIntermediates/Virtual Tags/InstallationBuildProductsLocation/Applications/VirtualTags.app/Frameworks/Security.framework did not contain an Info.plist (in target 'VirtualTags' from project 'Virtual Tags') error: Framework /Users/fbartolom/Library/Developer/Xcode/DerivedData/Virtual_Tags-apzduassdiglhcapscsllvzbfgid/Build/Intermediates.noindex/ArchiveIntermediates/Virtual Tags/InstallationBuildProductsLocation/Applications/VirtualTags.app/Frameworks/CloudKit.framework did not contain an Info.plist (in target 'VirtualTags' from project 'Virtual Tags') MacBook Pro M5, Tahoe 26.1, Xcode 26.1.1
2
0
252
Dec ’25
Certificate revocation check with SecPolicyCreateRevocation/SecTrustEvaluateWithError does not work
When trying to check if a certificate has been revoked with SecPolicyCreateRevocation (Flags: kSecRevocationUseAnyAvailableMethod | kSecRevocationRequirePositiveResponse) and SecTrustEvaluateWithError I always get the result error code errSecIncompleteCertRevocationCheck, regardless if the certificate was revoked or not. Reproduction: Execute the program from the attached Xcode project (See Feedback FB21224106). Error output: Error: Error Domain=NSOSStatusErrorDomain Code=-67635 ""revoked.badssl.com","E8","ISRG Root X1" certificates do not meet pinning requirements" UserInfo={NSLocalizedDescription="revoked.badssl.com","E8","ISRG Root X1" certificates do not meet pinning requirements, NSUnderlyingError=0x6000018d48a0 {Error Domain=NSOSStatusErrorDomain Code=-67635 "Certificate 0 “revoked.badssl.com” has errors: Failed to check revocation;" UserInfo={NSLocalizedDescription=Certificate 0 “revoked.badssl.com” has errors: Failed to check revocation;}}} To me it looks like that the revocation check just fails („Failed to check revocation;“), no further information is provided by the returned error. In the example the certificate chain of https://revoked.badssl.com (default code) and https://badssl.com is verified (to switch see comments in the code). I have a proxy configured in the system, I assume that the revocation check will use it. On the same machine, the browsers (Safari and Google Chrome) can successfully detect if the certificate was revoked (revoked.badssl.com) or not (badssl.com) without further changes in the system/proxy settings. Note: The example leaks some memory, it’s just a test program. Am I missing something? Feedback: FB21224106
6
0
789
Dec ’25
DTLS Handshake Fails When App Is in Background – Is This an iOS Limitation?
Hello, We are facing an issue with performing a DTLS handshake when our iOS application is in the background. Our app (Vocera Collaboration Suite – VCS) uses secure DTLS-encrypted communication for incoming VoIP calls. Problem Summary: When the app is in the background and a VoIP PushKit notification arrives, we attempt to establish a DTLS handshake over our existing socket. However, the handshake consistently fails unless the app is already in the foreground. Once the app is foregrounded, the same DTLS handshake logic succeeds immediately. Key Questions: Is performing a DTLS handshake while the app is in the background technically supported by iOS? Or is this an OS-level limitation by design? If not supported, what is the Apple-recommended alternative to establish secure DTLS communication for VoIP flows without bringing the app to the foreground? Any guidance or clarification from Apple engineers or anyone who has solved a similar problem would be greatly appreciated. Thank you.
5
0
348
Feb ’26
ATS on watchOS is fundamentally broken for generic client apps. Why is Apple killing innovation?
I spent the entire day debugging a network issue on my Apple Watch app, only to realize the problem isn't my code—it's Apple's inflexible design. The Context: I am building a generic MCP (Model Context Protocol) client for watchOS. The nature of this app is to allow users to input their own server URLs (e.g., a self-hosted endpoint, or public services like GitHub's MCP server) to interact with LLMs and tools. The Problem: When using standard URLSession to connect to widely trusted, public HTTPS endpoints (specifically GitHub's official MCP server at https://mcp.github.com), the connection is forcefully terminated by the OS with NSURLErrorDomain Code=-1200 (TLS handshake failed). The Analysis: This is caused by App Transport Security (ATS). ATS is enforcing a draconian set of security standards (specific ciphers, forward secrecy requirements, etc.) that many perfectly valid, secure, and globally accepted servers do not strictly meet 100%. The Absurdity: We cannot whitelist domains: Since this is a generic client, I cannot add NSExceptionDomains to Info.plist because I don't know what URL the user will input. We cannot disable ATS: Adding NSAllowsArbitraryLoads is a guaranteed rejection during App Store review for a general-purpose app without a "compelling reason" acceptable to Apple. The result: My app is effectively bricked. It cannot connect to GitHub. It cannot connect to 90% of the user's self-hosted servers. The Question: Is the Apple Watch just a toy? How does Apple expect us to build flexible, professional tools when the OS acts like a nanny that blocks connections to GitHub? We need a way to bypass strict ATS checks for user-initiated connections in generic network tools, similar to how curl -k or other developer tools work. The current "all-or-nothing" policy is suffocating.
2
0
377
Nov ’25
SecurityAgent taking focus for plugin in macOS 26.1
We have a custom SecurityAgentPlugin that is triggered by multiple authorizationdb entries. Some customers report that the SecurityAgent process takes window focus even though no UI or windows are displayed. Our plugin explicitly ignores the _securityAgent user and does not show any UI for that user. However, in macOS 26.1, it appears that the plugin still causes the SecurityAgent to take focus as soon as it is triggered. Is this a change in macOS 26.1 or a bug? Can we do anything to prevent "focus stealing"?
27
3
4.7k
4w
Archived app failing to get root certificates for SSL websocket connection
I've had a Unreal Engine project that uses libwebsocket to make a websocket connection with SSL to a server. Recently I made a build using Unreal Engine 5.4.4 on MacOS Sequoia 15.5 and XCode 16.4 and for some reason the websocket connection now fails because it can't get the local issuer certificate. It fails to access the root certificate store on my device (Even though, running the project in the Unreal Editor works fine, it's only when making a packaged build with XCode that it breaks) I am not sure why this is suddenly happening now. If I run it in the Unreal editor on my macOS it works fine and connects. But when I make a packaged build which uses XCode to build, it can't get the local issuer certificate. I tried different code signing options, such as sign to run locally or just using sign automatically with a valid team, but I'm not sure if code signing is the cause of this issue or not. This app is only for development and not meant to be published, so that's why I had been using sign to run locally, and that used to work fine but not anymore. Any guidance would be appreciated, also any information on what may have changed that now causes this certificate issue to happen. I know Apple made changes and has made notarizing MacOS apps mandatory, but I'm not sure if that also means a non-notarized app will now no longer have access to the root certificate store of a device, in my research I haven't found anything about that specifically, but I'm wondering if any Apple engineers might know something about this that hasn't been put out publicly.
6
0
171
Nov ’25
Capturing screen buffer at macOS Login Window with ScreenCaptureKit and PrivilegedHelper
I am developing a remote support tool for macOS. While we have successfully implemented a Privileged Helper Tool and LaunchDaemon architecture that works within an active Aqua session, we have observed a total failure to capture the screen buffer or receive input at the macOS Login Window. Our observation of competitor software (AnyDesk, TeamViewer) shows they maintain graphical continuity through logout/restart. We are seeking the official architectural path to replicate this system-level access. Current Technical Implementation Architecture: A root-level LaunchDaemon manages the persistent network connection. A PrivilegedHelperTool (installed in /Library/PrivilegedHelperTools/) is used for elevated tasks. Environment: Tested on macOS 14.x (Sonoma) and macOS 15.x (Sequoia) on Apple Silicon. Capture Methods: We have implemented ScreenCaptureKit (SCK) as the primary engine and CGDisplayCreateImage as a fallback. Binary Status: All components are signed with a Developer ID and have been successfully Notarized. Observed Behavior & Blockers The "Aqua" Success: Within a logged-in user session, our CGI correctly identifies Display IDs and initializes the capture stream. Remote control is fully functional. The "Pre-Login" Failure: When the Mac is at the Login Window (no user logged in), the following occurs: The Daemon remains active, but the screen capture buffer returns NULL or an empty frame. ScreenCaptureKit fails to initialize, citing a lack of graphical context. No TCC (Transparency, Consent, and Control) prompt can appear because no user session exists. The "Bootstrap" Observation: We have identified that the loginwindow process exists in a restricted Mach bootstrap namespace that our Daemon (running in the System domain) cannot natively bridge. Comparative Analysis (Competitor Benchmarking) We have analyzed established remote desktop solutions like AnyDesk and Jump Desktop to understand their success at the login screen. Our findings suggest: Dual-Context Execution: They appear to use a Global LaunchAgent with LimitLoadToSessionType = ["LoginWindow"]. This allows a child process to run as root inside the login window’s graphical domain. Specialized Entitlements: These apps have migrated to the com.apple.developer.persistent-content-capture entitlement. This restricted capability allows them to bypass the weekly/monthly TCC re-authorization prompts and function in unattended scenarios where a user cannot click "Allow." Questions Entitlement Requirement: Is the persistent-content-capture entitlement the only supported way for a third-party app to capture the LoginWindow buffer without manual user intervention? LaunchAgent Strategy: To gain a graphical context at the login screen, is it recommended to load a specialized agent into the loginwindow domain via launchctl bootstrap loginwindow ...? ScreenCaptureKit vs. Legacy: Does ScreenCaptureKit officially support the LoginWindow session, or does it require an active Aqua session to initialize? MDM Bypass: For Enterprise environments, can a Privacy Preferences Policy Control (PPPC) payload grant "Screen Recording" to a non-entitled Daemon specifically for the login window context?
Replies
1
Boosts
0
Views
444
Activity
Jan ’26
Support for Additional Key Exchange Groups (SecP256r1MLKEM768 and SecP384r1MLKEM1024) on iOS 26 for WKWebView and NSURLSession
As part of iOS 26, we get X25519MLKEM768 key exchange group support, but SecP256r1MLKEM768 and SecP384r1MLKEM1024 are not supported. Is there any way to enable these key exchange groups on iOS 26? We need them for WKWebView and NSURLSession. STEPS TO REPRODUCE On iOS 26, connect to the PQC server using Safari. The key exchange group is limited to X25519MLKEM768.
Replies
2
Boosts
0
Views
211
Activity
Feb ’26
App Management permission cannot be given to non-bundled apps
We are using a java program as an installer for a software suite. This program is bundled inside a signed and notarized Mac app, but it uses the system installed Java (from env). For installing software, it requires the App Management permission (currently under System Settings › Privacy & Security › App Management). Since the program runs via the system provided Java executable, that one is the executable, that needs said permission. In the past, it was possible to add java to said permissions list. With macOS 26.2 it is no longer possible. I think, this change happened with 26.2. It was definitely still working with macOS 15 (I can reproduce it there), and I am confident, that it also still worked under 26.1. In Console.app I can see errors like this one /AppleInternal/Library/BuildRoots/4~CCKzugBjdyGA3WHu9ip90KmiFMk4I5oJfOTbSBk/Library/Caches/com.apple.xbs/Sources/SecurityPref/Extension/Privacy/TCC+PrivacyServicesProvider.swift:227 add(record:to:) No bundle or no bundle ID found for record TCCRecord(identifier: "/opt/homebrew/Cellar/sdkman-cli/5.19.0/libexec/candidates/java/11.0.29-tem/bin/rmic", identifierType: SecurityPrivacyExtension.TCCIdentifierType.path, access: SecurityPrivacyExtension.TCCAccess.full, managed: false, allowStandardUserToSetSystemService: false, subjectIdentityBundleIdentifier: nil, indirectObjectIdentityBundleIdentifier: nil, indirectObjectIdentityFileProviderIdentifier: nil, tccAuthorization: <OS_tcc_authorization_record: 0xa97d0ba80>) This is reproducible for various different Java installations. I can also not add Java to the other permissions that I tried. Since Java is not installed in a bundled app but instead as a UNIX executable in a bin-folder, the error No bundle or no bundle ID found for record makes sense. I expect this to also affect other use cases where programs are provided as UNIX executables such as Python or C-Compilers like g++. While it is possible to bundle an entire JRE inside each app, we intentionally chose not to as this massively increases app size. If this issue is not resolved or a workaround can be found, this is the only option that remains for us. I am however worried that there are other use cases where this is not an option.
Replies
1
Boosts
0
Views
162
Activity
Jan ’26
Signed app can't be verified
I've signed an app, zipped it, and uploaded it to github. When I download it on another Mac, I get "it can't be opened because it could not be verified for malware". But on that computer, I can verify it with codesign, and it appears to be correct (as far as I can tell). I can copy/paste the app from my other Mac, and that copy will run without problem. sys_policy, however, gives: Notary Ticket Missing File: ReView.app Severity: Fatal Full Error: A Notarization ticket is not stapled to this application. Type: Distribution Error This is the same for the copy that runs, and the copy that doesn't. The difference between them appears to be a quarantine xattr. I can delete this, and the app launches without incident. Is this expected? Why should a signed app be quarantined just because it's been downloaded? The whole point of paying the fee is to avoid the security obstacles...! ;-)
Replies
3
Boosts
0
Views
882
Activity
Feb ’26
App Store Requirements: SSL Certificates for Home Raspberry Pi Servers – Practical Solutions?
Hello, A customer has requested the development of a home assistance app to be published on the App Store. The app will connect to a server running locally at the end user's home, for example on a Raspberry Pi. Users would enter the IP address or hostname of their personal server into the app. A strict requirement is that, for data protection reasons, there must not be any proxy server. The app should only communicate directly with the local server (e.g., Raspberry Pi). We are able to solve technical challenges such as DNS, dynamic IP, and port forwarding, router configuration. However, I'm concerned about Apple's requirement that the endpoint – in this case, the Raspberry Pi at the user's home – must not use self-signed SSL certificates. While it may be technically possible to secure the home server with a certificate provider like Let's Encrypt, it is unrealistic to expect a typical user with no technical training to accomplish this setup independently. Is there a recommended solution to this problem, particularly in the context of IoT devices and apps? Any advice or experiences would be deeply appreciated.
Replies
1
Boosts
0
Views
124
Activity
Jan ’26
Does accessing multiple Keychain items with .userPresence force multiple biometric prompts despite reuse duration?
Hi everyone, I'm working on an app that stores multiple secrets in the Keychain, each protected with .userPresence. My goal is to authenticate the user once via FaceID/TouchID and then read multiple Keychain items without triggering subsequent prompts. I am reusing the same LAContext instance for these operations, and I have set: context.touchIDAuthenticationAllowableReuseDuration = LATouchIDAuthenticationMaximumAllowableReuseDuration However, I'm observing that every single SecItemCopyMatching call triggers a new FaceID/TouchID prompt, even if they happen within seconds of each other using the exact same context. Here is a simplified flow of what I'm doing: Create a LAContext. Set touchIDAuthenticationAllowableReuseDuration to max. Perform a query (SecItemCopyMatching) for Item A, passing [kSecUseAuthenticationContext: context]. Result: System prompts for FaceID. Success. Immediately perform a query (SecItemCopyMatching) for Item B, passing the same [kSecUseAuthenticationContext: context]. Result: System prompts for FaceID again. My question is: Does the .userPresence access control flag inherently force a new user interaction for every Keychain access, regardless of the LAContext reuse duration? Is allowableReuseDuration only applicable for LAContext.evaluatePolicy calls and not for SecItem queries? If so, is there a recommended pattern for "unlocking" a group of Keychain items with a single biometric prompt? Environment: iOS 17+, Swift. Thanks!
Replies
3
Boosts
0
Views
569
Activity
Jan ’26
Limit access for a file/folder to a given application
So I'm aware that Apple can designate a folder as a "data vault", and access to that folder is limited to applications that have a specific entitlement. I was wondering if there was an equivalent (or the same, I'm not fussy :) feature available to third parties, even if only during the app-store submission ? To avoid the X-Y problem, what I want to do is have a launch agent with access to a SQLite database, and I want only that launch agent to have access. Any reads of the database will have to be done through an XPC call from the main user-facing application. I want to store private data into that database, and I don't want there to be any way for any other application to read it. If there's a way to do that without data-vaults I'm all ears :) I'm not sure if this is really the right place, perhaps the core-os forum would be better, but since the Apple solution is gate-kept by entitlements, I thought I'd start here :)
Replies
5
Boosts
0
Views
238
Activity
Jan ’26
Hardware Memory Tag (MIE) enforcement outside of debugger
(Xcode 26.2, iPhone 17 Pro) I can't seem to get hardware tag checks to work in an app launched without the special "Hardware Memory Tagging" diagnostics. In other words, I have been unable to reproduce the crash example at 6:40 in Apple's video "Secure your app with Memory Integrity Enforcement". When I write a heap overflow or a UAF, it is picked up perfectly provided I enable the "Hardware Memory Tagging" feature under Scheme Diagnostics. If I instead add the Enhanced Security capability with the memory-tagging related entitlements: I'm seeing distinct memory tags being assigned in pointers returned by malloc (without the capability, this is not the case) Tag mismatches are not being caught or enforced, regardless of soft mode The behaviour is the same whether I launch from Xcode without "Hardware Memory Tagging", or if I launch the app by tapping it on launchpad. In case it was related to debug builds, I also tried creating an ad hoc IPA and it didn't make any difference. I realise there's a wrinkle here that the debugger sets MallocTagAll=1, so possibly it will pick up a wider range of issues. However I would have expected that a straight UAF would be caught. For example, this test code demonstrates that tagging is active but it doesn't crash: #define PTR_TAG(p) ((unsigned)(((uintptr_t)(p) >> 56) & 0xF)) void *p1 = malloc(32); void *p2 = malloc(32); void *p3 = malloc(32); os_log(OS_LOG_DEFAULT, "p1 = %p (tag: %u)\n", p1, PTR_TAG(p1)); os_log(OS_LOG_DEFAULT, "p2 = %p (tag: %u)\n", p2, PTR_TAG(p2)); os_log(OS_LOG_DEFAULT, "p3 = %p (tag: %u)\n", p3, PTR_TAG(p3)); free(p2); void *p2_realloc = malloc(32); os_log(OS_LOG_DEFAULT, "p2 after free+malloc = %p (tag: %u)\n", p2_realloc, PTR_TAG(p2_realloc)); // Is p2_realloc the same address as p2 but different tag? os_log(OS_LOG_DEFAULT, "Same address? %s\n", ((uintptr_t)p2 & 0x00FFFFFFFFFFFFFF) == ((uintptr_t)p2_realloc & 0x00FFFFFFFFFFFFFF) ? "YES" : "NO"); // Now try to use the OLD pointer p2 os_log(OS_LOG_DEFAULT, "Attempting use-after-free via old pointer p2...\n"); volatile char c = *(volatile char *)p2; // Should this crash? os_log(OS_LOG_DEFAULT, "Read succeeded! Value: %d\n", c); Example output: p1 = 0xf00000b71019660 (tag: 15) p2 = 0x200000b711958c0 (tag: 2) p3 = 0x300000b711958e0 (tag: 3) p2 after free+malloc = 0x700000b71019680 (tag: 7) Same address? NO Attempting use-after-free via old pointer p2... Read succeeded! Value: -55 For reference, these are my entitlements. [Dict] [Key] application-identifier [Value] [String] … [Key] com.apple.developer.team-identifier [Value] [String] … [Key] com.apple.security.hardened-process [Value] [Bool] true [Key] com.apple.security.hardened-process.checked-allocations [Value] [Bool] true [Key] com.apple.security.hardened-process.checked-allocations.enable-pure-data [Value] [Bool] true [Key] com.apple.security.hardened-process.dyld-ro [Value] [Bool] true [Key] com.apple.security.hardened-process.enhanced-security-version [Value] [Int] 1 [Key] com.apple.security.hardened-process.hardened-heap [Value] [Bool] true [Key] com.apple.security.hardened-process.platform-restrictions [Value] [Int] 2 [Key] get-task-allow [Value] [Bool] true What do I need to do to make Memory Integrity Enforcement do something outside the debugger?
Replies
6
Boosts
0
Views
1.3k
Activity
Feb ’26
Exporting and re-importing ECC keys with file-based keychain
I'm trying to export and re-import a P-256 private key that was originally generated via SecKeyCreateRandomKey(), but I keep running into roadblocks. The key is simply exported via SecItemExport() with format formatWrappedPKCS8, and I did set a password just to be sure. Do note that I must use the file-based keychain, as the data protection keychain requires a restricted entitlement and I'm not going to pay a yearly fee just to securely store some private keys for a personal project. The 7-day limit for unsigned/self-signed binaries isn't feasible either. Here's pretty much everything I could think of trying: Simply using SecItemImport() does import the key, but I cannot set kSecAttrLabel and more importantly: kSecAttrApplicationTag. There just isn't any way to pass these attributes upfront, so it's always imported as Imported Private Key with an empty comment. Keys don't support many attributes to begin with and I need something that's unique to my program but shared across all the relevant key entries, otherwise it's impossible to query for only my program's keys. kSecAttrLabel is already used for something else and is always unique, which really only leaves kSecAttrApplicationTag. I've already accepted that this can be changed via Keychain Access, as this attribute should end up as the entry's comment. At least, that's how it works with SecKeyCreateRandomKey() and SecItemCopyMatching(). I'm trying to get that same behaviour for imports. Running SecItemUpdate() afterwards to set these 2 attributes doesn't work either, as now the kSecAttrApplicationTag is suddenly used for the entry's label instead of the comment. Even setting kSecAttrComment (just to be certain) doesn't change the comment. I think kSecAttrApplicationTag might be a creation-time attribute only, and since SecItemImport() already created a SecKey I will never be able to set this. It likely falls back to updating the label because it needs to target something that is still mutable? Using SecItemImport() with a nil keychain (i.e. create a transient key), then persisting that with SecItemAdd() via kSecValueRef does allow me to set the 2 attributes, but now the ACL is lost. Or more precise: the ACL does seem to exist as any OS prompts do show the label I originally set for the ACL, but in Keychain Access it shows as Allow all applications to access this item. I'm looking to enable Confirm before allowing access and add my own program to the Always allow access by these applications list. Private keys outright being open to all programs is of course not acceptable, and I can indeed access them from other programs without any prompts. Changing the ACL via SecKeychainItemSetAccess() after SecItemAdd() doesn't seem to do anything. It apparently succeeds but nothing changes. I also reopened Keychain Access to make sure it's not a UI "caching" issue. Creating a transient key first, then getting the raw key via SecKeyCopyExternalRepresentation() and passing that to SecItemAdd() via kSecValueData results in The specified attribute does not exist. This error only disappears if I remove almost all of the attributes. I can pass only kSecValueData, kSecClass and kSecAttrApplicationTag, but then I get The specified item already exists in the keychain errors. I found a doc that explains what determines uniqueness, so here are the rest of the attributes I'm using for SecItemAdd(): kSecClass: not mentioned as part of the primary key but still required, otherwise you'll get One or more parameters passed to a function were not valid. kSecAttrLabel: needed for my use case and not part of the primary key either, but as I said this results in The specified attribute does not exist. kSecAttrApplicationLabel: The specified attribute does not exist. As I understand it this should be the SHA1 hash of the public key, passed as Data. Just omitting it would certainly be an option if the other attributes actually worked, but right now I'm passing it to try and construct a truly unique primary key. kSecAttrApplicationTag: The specified item already exists in the keychain. kSecAttrKeySizeInBits: The specified attribute does not exist. kSecAttrEffectiveKeySize: The specified attribute does not exist. kSecAttrKeyClass: The specified attribute does not exist. kSecAttrKeyType: The specified attribute does not exist. It looks like only kSecAttrApplicationTag is accepted, but still ignored for the primary key. Even entering something that is guaranteed to be unique still results in The specified item already exists in the keychain, so I think might actually be targeting literally any key. I decided to create a completely new keychain and import it there (which does succeed), but the key is completely broken. There's no Kind and Usage at the top of Keychain Access and the table view just below it shows symmetric key instead of private. The kSecAttrApplicationTag I'm passing is still being used as the label instead of the comment and there's no ACL. I can't even delete this key because Keychain Access complains that A missing value was detected. It seems like the key doesn't really contain anything unique for its primary key, so it will always match any existing key. Using SecKeyCreateWithData() and then using that key as the kSecValueRef for SecItemAdd() results in A required entitlement isn't present. I also have to add kSecUseDataProtectionKeychain: false to SecItemAdd() (even though that should already be the default) but then I get The specified item is no longer valid. It may have been deleted from the keychain. This occurs even if I decrypt the PKCS8 manually instead of via SecItemImport(), so it's at least not like it's detecting the transient key somehow. No combination of kSecAttrIsPermanent, kSecUseDataProtectionKeychain and kSecUseKeychain on either SecKeyCreateWithData() or SecItemAdd() changes anything. I also tried PKCS12 despite that it always expects an "identity" (key + cert), while I only have (and need) a private key. Exporting as formatPKCS12 and importing it with itemTypeAggregate (or itemTypeUnknown) does import the key, and now it's only missing the kSecAttrApplicationTag as the original label is automatically included in the PKCS12. The outItems parameter contains an empty list though, which sort of makes sense because I'm not importing a full "identity". I can at least target the key by kSecAttrLabel for SecItemUpdate(), but any attempt to update the comment once again changes the label so it's not really any better than before. SecPKCS12Import() doesn't even import anything at all, even though it does return errSecSuccess while also passing kSecImportExportKeychain explicitly. Is there literally no way?
Replies
4
Boosts
0
Views
1.1k
Activity
Jan ’26
How do I prevent screenshots using SwiftUI?
Hi Team, How do I prevent screenshots using SwiftUI. I was using this solution on UIKit: extension UIView { func makeSecure() { DispatchQueue.main.async { let protectedView = UIView() self.superview?.addSubview(protectedView) // constraints... let secureView = SecureView() self.superview?.addSubview(secureView) // constraints... secureView.addSecureSubview(self) // constraints... } } } class SecureView: UIView { private lazy var secureField: UIView = { var secureField: UIView = UIView() // ... if let secureContainer = SecureField().secureContainer { secureField = secureContainer } ... return secureField }() required init() { ... } } Is it posible to do the same thing using SwiftUI. Do we have an example? What would you recommend when we work with confidencial information in SwiftUI like bank account information? Thanks in advance!
Replies
0
Boosts
0
Views
207
Activity
Dec ’25
Change ACL of existing Private key of system keychain
Hi, everyone! Is there any way to change ACL of existing Private key in system keychain using MDM? We would like to add the binary or .app to access list of the key. I tried to send script via MDM which imported/exported our certificate with private key with required ACL. But can we change it without import/export?
Replies
1
Boosts
0
Views
3.2k
Activity
Dec ’25
Unexpected errSecInteractionNotAllowed (-25308) When Reading Keychain Item with kSecAttrAccessibleAfterFirstUnlock in Background
Hi everyone, I’m encountering an unexpected Keychain behavior in a production environment and would like to confirm whether this is expected or if I’m missing something. In my app, I store a deviceId in the Keychain based on the classic KeychainItemWrapper implementation. I extended it by explicitly setting: kSecAttrAccessible = kSecAttrAccessibleAfterFirstUnlock My understanding is that kSecAttrAccessibleAfterFirstUnlock should allow Keychain access while the app is running in the background, as long as the device has been unlocked at least once after reboot. However, after the app went live, I observed that when the app performs background execution (e.g., triggered by background tasks / silent push), Keychain read attempts intermittently fail with: errSecInteractionNotAllowed (-25308) This seems inconsistent with the documented behavior of kSecAttrAccessibleAfterFirstUnlock. Additional context: The issue never occurs in foreground. The issue does not appear on development devices. User devices are not freshly rebooted when this happens. The Keychain item is created successfully; only background reads fail. Setting the accessibility to kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly produces the same result. Questions: Under what circumstances can kSecAttrAccessibleAfterFirstUnlock still cause a -25308 error? Is there any known restriction when accessing Keychain while the app is running in background execution contexts? Could certain system states (Low Power Mode, Background App Refresh conditions, device lock state, etc.) cause Keychain reads to be blocked unexpectedly? Any insights or similar experiences would be greatly appreciated. Thank you!
Replies
3
Boosts
0
Views
706
Activity
Dec ’25
Persistent Tokens for Keychain Unlock in Platform SSO
While working with Platform SSO on macOS, I’m trying to better understand how the system handles cases where a user’s local account password becomes unsynchronized with their Identity Provider (IdP) password—for example, when the device is offline during a password change. My assumption is that macOS may store some form of persistent token during the Platform SSO user registration process (such as a certificate or similar credential), and that this token could allow the system to unlock the user’s login keychain even if the local password no longer matches the IdP password. I’m hoping to get clarification on the following: Does macOS actually use a persistent token to unlock the login keychain when the local account password is out of sync with the IdP password? If so, how is that mechanism designed to work? If such a capability exists, is it something developers can leverage to enable a true passwordless authentication experience at the login window and lock screen (i.e., avoiding the need for a local password fallback)? I’m trying to confirm what macOS officially supports so I can understand whether passwordless login is achievable using the persistent-token approach. Thanks in advance for any clarification.
Replies
1
Boosts
3
Views
294
Activity
Dec ’25
KeyChain Sharing with App Extensions
Hi, We are trying to use Apple Security API for KeyChain Services. Using the common App Group : Specifying the common app group in the "kSecAttrAccessGroup" field of the KeyChain query, allowed us to have a shared keychains for different apps (targets) in the app group, but this did not work for extensions. Enabling the KeyChain Sharing capability : We enabled the KeyChain Sharing Ability in the extensions and the app target as well, giving a common KeyChain Access group. Specifying this in the kSecAttrAccessGroup field also did not work. This was done in XCode as we were unable to locate it in the Developer portal in Indentifiers. We tried specifying "$AppIdentifier.KeyChainSharingGroup" in the kSecAttrAccessGroup field , but this did not work as well The error code which we get in all these 3 cases when trying to access the Keychain from the extension is error code 25291 (errSecNotAvailable). The Documentation says this error comes when "No Trust Results are available" and printing the error in xcode using the status says "No keychain is available. The online Documentation says that it is possible to share keychain with extensions, but by far we are unable to do it with the methods suggested. Do we need any special entitlement for this or is there something we are missing while using these APIs? We really appreciate any and all help in solving this issue! Thank you
Replies
4
Boosts
0
Views
309
Activity
Dec ’25
Upon trying to archive I got funny errors preventing it
When I try to archive an app in order to submit it to the App Store I receive the following errors I do not know how to fix: error: Framework /Users/fbartolom/Library/Developer/Xcode/DerivedData/Virtual_Tags-apzduassdiglhcapscsllvzbfgid/Build/Intermediates.noindex/ArchiveIntermediates/Virtual Tags/InstallationBuildProductsLocation/Applications/VirtualTags.app/Frameworks/StoreKit.framework did not contain an Info.plist (in target 'VirtualTags' from project 'Virtual Tags') error: Framework /Users/fbartolom/Library/Developer/Xcode/DerivedData/Virtual_Tags-apzduassdiglhcapscsllvzbfgid/Build/Intermediates.noindex/ArchiveIntermediates/Virtual Tags/InstallationBuildProductsLocation/Applications/VirtualTags.app/Frameworks/Security.framework did not contain an Info.plist (in target 'VirtualTags' from project 'Virtual Tags') error: Framework /Users/fbartolom/Library/Developer/Xcode/DerivedData/Virtual_Tags-apzduassdiglhcapscsllvzbfgid/Build/Intermediates.noindex/ArchiveIntermediates/Virtual Tags/InstallationBuildProductsLocation/Applications/VirtualTags.app/Frameworks/CloudKit.framework did not contain an Info.plist (in target 'VirtualTags' from project 'Virtual Tags') MacBook Pro M5, Tahoe 26.1, Xcode 26.1.1
Replies
2
Boosts
0
Views
252
Activity
Dec ’25
Certificate revocation check with SecPolicyCreateRevocation/SecTrustEvaluateWithError does not work
When trying to check if a certificate has been revoked with SecPolicyCreateRevocation (Flags: kSecRevocationUseAnyAvailableMethod | kSecRevocationRequirePositiveResponse) and SecTrustEvaluateWithError I always get the result error code errSecIncompleteCertRevocationCheck, regardless if the certificate was revoked or not. Reproduction: Execute the program from the attached Xcode project (See Feedback FB21224106). Error output: Error: Error Domain=NSOSStatusErrorDomain Code=-67635 ""revoked.badssl.com","E8","ISRG Root X1" certificates do not meet pinning requirements" UserInfo={NSLocalizedDescription="revoked.badssl.com","E8","ISRG Root X1" certificates do not meet pinning requirements, NSUnderlyingError=0x6000018d48a0 {Error Domain=NSOSStatusErrorDomain Code=-67635 "Certificate 0 “revoked.badssl.com” has errors: Failed to check revocation;" UserInfo={NSLocalizedDescription=Certificate 0 “revoked.badssl.com” has errors: Failed to check revocation;}}} To me it looks like that the revocation check just fails („Failed to check revocation;“), no further information is provided by the returned error. In the example the certificate chain of https://revoked.badssl.com (default code) and https://badssl.com is verified (to switch see comments in the code). I have a proxy configured in the system, I assume that the revocation check will use it. On the same machine, the browsers (Safari and Google Chrome) can successfully detect if the certificate was revoked (revoked.badssl.com) or not (badssl.com) without further changes in the system/proxy settings. Note: The example leaks some memory, it’s just a test program. Am I missing something? Feedback: FB21224106
Replies
6
Boosts
0
Views
789
Activity
Dec ’25
DTLS Handshake Fails When App Is in Background – Is This an iOS Limitation?
Hello, We are facing an issue with performing a DTLS handshake when our iOS application is in the background. Our app (Vocera Collaboration Suite – VCS) uses secure DTLS-encrypted communication for incoming VoIP calls. Problem Summary: When the app is in the background and a VoIP PushKit notification arrives, we attempt to establish a DTLS handshake over our existing socket. However, the handshake consistently fails unless the app is already in the foreground. Once the app is foregrounded, the same DTLS handshake logic succeeds immediately. Key Questions: Is performing a DTLS handshake while the app is in the background technically supported by iOS? Or is this an OS-level limitation by design? If not supported, what is the Apple-recommended alternative to establish secure DTLS communication for VoIP flows without bringing the app to the foreground? Any guidance or clarification from Apple engineers or anyone who has solved a similar problem would be greatly appreciated. Thank you.
Replies
5
Boosts
0
Views
348
Activity
Feb ’26
ATS on watchOS is fundamentally broken for generic client apps. Why is Apple killing innovation?
I spent the entire day debugging a network issue on my Apple Watch app, only to realize the problem isn't my code—it's Apple's inflexible design. The Context: I am building a generic MCP (Model Context Protocol) client for watchOS. The nature of this app is to allow users to input their own server URLs (e.g., a self-hosted endpoint, or public services like GitHub's MCP server) to interact with LLMs and tools. The Problem: When using standard URLSession to connect to widely trusted, public HTTPS endpoints (specifically GitHub's official MCP server at https://mcp.github.com), the connection is forcefully terminated by the OS with NSURLErrorDomain Code=-1200 (TLS handshake failed). The Analysis: This is caused by App Transport Security (ATS). ATS is enforcing a draconian set of security standards (specific ciphers, forward secrecy requirements, etc.) that many perfectly valid, secure, and globally accepted servers do not strictly meet 100%. The Absurdity: We cannot whitelist domains: Since this is a generic client, I cannot add NSExceptionDomains to Info.plist because I don't know what URL the user will input. We cannot disable ATS: Adding NSAllowsArbitraryLoads is a guaranteed rejection during App Store review for a general-purpose app without a "compelling reason" acceptable to Apple. The result: My app is effectively bricked. It cannot connect to GitHub. It cannot connect to 90% of the user's self-hosted servers. The Question: Is the Apple Watch just a toy? How does Apple expect us to build flexible, professional tools when the OS acts like a nanny that blocks connections to GitHub? We need a way to bypass strict ATS checks for user-initiated connections in generic network tools, similar to how curl -k or other developer tools work. The current "all-or-nothing" policy is suffocating.
Replies
2
Boosts
0
Views
377
Activity
Nov ’25
SecurityAgent taking focus for plugin in macOS 26.1
We have a custom SecurityAgentPlugin that is triggered by multiple authorizationdb entries. Some customers report that the SecurityAgent process takes window focus even though no UI or windows are displayed. Our plugin explicitly ignores the _securityAgent user and does not show any UI for that user. However, in macOS 26.1, it appears that the plugin still causes the SecurityAgent to take focus as soon as it is triggered. Is this a change in macOS 26.1 or a bug? Can we do anything to prevent "focus stealing"?
Replies
27
Boosts
3
Views
4.7k
Activity
4w
Archived app failing to get root certificates for SSL websocket connection
I've had a Unreal Engine project that uses libwebsocket to make a websocket connection with SSL to a server. Recently I made a build using Unreal Engine 5.4.4 on MacOS Sequoia 15.5 and XCode 16.4 and for some reason the websocket connection now fails because it can't get the local issuer certificate. It fails to access the root certificate store on my device (Even though, running the project in the Unreal Editor works fine, it's only when making a packaged build with XCode that it breaks) I am not sure why this is suddenly happening now. If I run it in the Unreal editor on my macOS it works fine and connects. But when I make a packaged build which uses XCode to build, it can't get the local issuer certificate. I tried different code signing options, such as sign to run locally or just using sign automatically with a valid team, but I'm not sure if code signing is the cause of this issue or not. This app is only for development and not meant to be published, so that's why I had been using sign to run locally, and that used to work fine but not anymore. Any guidance would be appreciated, also any information on what may have changed that now causes this certificate issue to happen. I know Apple made changes and has made notarizing MacOS apps mandatory, but I'm not sure if that also means a non-notarized app will now no longer have access to the root certificate store of a device, in my research I haven't found anything about that specifically, but I'm wondering if any Apple engineers might know something about this that hasn't been put out publicly.
Replies
6
Boosts
0
Views
171
Activity
Nov ’25