We are trying to develop an app that will be responsible for managing 5000+ managed iPads through Intune MDM. The user flow is to have a device locked to a single app when a user is not logged in, but to make the device available to other apps once a user is authenticated.
We already tried UIAccessibility GuidedAccess Mode and autonomous single app mode but those were not sufficient due to our need to be able to toggle this from the background. When the device may be asleep.
So another way we could achieve this functionality would be to control all app access under a launching mechanism. That way we could allow one app to be visible in our MDM configuration and try to access our business app through that using deep links.
If this were to work, we would have to be able to hide an app and still make it launchable from the manager.
Any ideas? Thanks
Security
RSS for tagSecure the data your app manages and control access to your app using the Security framework.
Posts under Security tag
178 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I'm sitting at my house and trying to sign my test device out of my apple ID so I can sign into a Sandbox user, but now I have an hour to kill because of this terribly broken "security" feature that thinks it's in an unfamiliar location, despite being at the only location it's ever known. Looks like I'll just be disabling this feature all together.
Especially as a device with Developer Mode enabled, which gets reset regularly, there should be additional options here. Come on!
iOS 18.4 introduced some requirements on the Key Usage of 802.1x server certificates, as described here. https://support.apple.com/en-us/121158
When using TLS_ECDHE_RSA or TLS_DHE_RSA cipher suites, 802.1X server certificates containing a Key Usage extension must have Digital Signature key usage set.
When using the TLS_RSA cipher suite, 802.1X server certificates containing a Key Usage extension must have Key Encipherment key usage set.
It reads like the change is supposed to affect 802.1x only. However, we have found out that the new restrictions are actually imposed on all TLS connections using the Network framework, including in Safari.
Unlike other certificate errors which can be either ignored by users (as in Safari) or by code (via sec_protocol_options_set_verify_block), these new ones can't. Even if passing completion(true) in the TLS verification block, the connection still ends up in waiting state with error -9830: illegal parameter.
I understand that these requirements are valid ones but as a generic TLS library I also expect that Network framework could at least allow overriding the behavior. The current treatment is not consistent with those on other certificate errors.
Since I can't upload certificates, here is how to reproduce a certificate that fails.
Create a OpenSSL config file test.cnf
[ req ]
default_bits = 2048
distinguished_name = dn
x509_extensions = v3_ca
prompt = no
[ dn ]
CN = example.com
[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = CA:TRUE
keyUsage = critical, keyCertSign, cRLSign
Generate certificate and private key
openssl req -x509 -new -nodes -keyout key.pem -out cert.pem -days 365 -config test.cnf
And here is the client code to test.
// Target server and port
let host = NWEndpoint.Host("example.com")
let port = NWEndpoint.Port("443")!
// Configure insecure TLS options
let tlsOptions = NWProtocolTLS.Options()
sec_protocol_options_set_verify_block(tlsOptions.securityProtocolOptions, { _, _, completion in
// Always trust
completion(true)
}, DispatchQueue.global())
let params = NWParameters(tls: tlsOptions)
let connection = NWConnection(host: .init(host), port: .init(rawValue: port)!, using: params)
connection.stateUpdateHandler = { newState in
switch newState {
case .ready:
print("TLS connection established")
case .failed(let error):
print("Connection failed: \(error)")
case .cancelled:
print("Connection canceled")
case .preparing:
print("Connection preparing")
case .waiting(let error):
print("Connection waiting: \(error)")
case .setup:
print("Connection setup")
default:
break
}
}
connection.start(queue: .global())
Output
Connection preparing
Connection waiting: -9830: illegal parameter
Previously reported as FB17099740
Our project currently uses a value called k_uuid as the unique identifier for each user. This value is generated based on the Identifier for Vendor (IDFV) and is stored both in the Keychain and local storage to prevent changes when the app is uninstalled and reinstalled.
However, we are now facing a critical issue. We plan to transfer the app from Developer Account A to Developer Account B using Apple’s App Transfer Process. During this transfer:
Our backend services will remain unchanged
Our development team will remain the same
Only the developer account will change
We understand that during this transfer process, the Team ID associated with the developer account will change, which in turn will make it impossible to access the existing Keychain data. As a result, if a user uninstalls and reinstalls the app after the transfer, their original unique ID (k_uuid) will change. This will lead to serious consequences, including:
Inability to recognize returning users
Loss of user data such as subscriptions, virtual currency, and usage history
Therefore, we urgently request guidance and assistance from Apple to:
Ensure that the k_uuid remains unchanged after the app transfer, or
Provide a solution that allows us to map users between the old and new environment, ensuring data continuity and integrity for all existing users
Topic:
App Store Distribution & Marketing
SubTopic:
App Store Connect
Tags:
Enterprise
App Store
Security
Hi,
It may be a stupid question, but we really wonder if there is a way for MDM to push a unique mTLS cert to our iOS application or if it can populate a client certificate in the iOS where our application can access it. Like browser app, how do browser mTLS certs get pushed?
Thanks,
Ying
Good day. The Infrastructure Security team my company is concerned about potential information security incidents in https://appstoreconnect.apple.com/. We intend to:
Collect logs of any activities within our organization (for example, someone adding a new user with administrative privileges or publishing a new application from a corporate account).
Automatically deliver these logs to our SIEM (e.g., Splunk), so that alerts can be generated and potential security incidents can be addressed, such as breaches of internal policies by an employee or a compromise of a corporate account associated with https://appstoreconnect.apple.com/.
Could you please advise on how this can be implemented?
Topic:
App Store Distribution & Marketing
SubTopic:
App Store Connect
Tags:
Security
App Store Connect API
Hello!
We have code that extracts macOS Installer package (.pkg, .mpkg) signature information using APIs defined in <xar/xar.h>
The code opens the package using ‘xar_open’ API like this.
func open(file: String) throws(XarError) {
xarfile = xar_open(file, READ)
if xarfile == nil {
throw .fileOpenError
}
}
This code produces a clang warning in our CI build system when built for macOS 12 and up.
'xar_open' was deprecated in macOS 12.0: xar is a deprecated file format and should not be used.
Question #1:
What is the appropriate / more preferred way to extract signature information from an Installer package given that xar related APIs are deprecated?
We use xar APIs to validate the package signature prior to installation to prevent packagers not signed by our team ID from being installed.
Question #2:
“xar is a deprecated file format and should not be used.”. Does this phrase refer to the file format that should be avoided or the API that extract signature information?
We distribute our product using Developer ID method that using pkg/mpkg formats which I believe internally follow the same structure as xar files. I hope this message does not mean we should rethink the distribution method for our products.
Thank you.
Filed FB FB17148233 as well.
I have developed a sample app following the example found Updating your app package installer to use the new Service Management API and referring this discussion on XPC Security.
The app is working fine, I have used Swift NSXPCConnection in favour of xpc_connection_create_mach_service used in the example. (I am running app directly from Xcode)
I am trying to set up security requirements for the client connection using setCodeSigningRequirement on the connection instance.
But it fails for even basic requirement connection.setCodeSigningRequirement("anchor apple").
Error is as follows.
cannot open file at line 46986 of [554764a6e7]
os_unix.c:46986: (0) open(/private/var/db/DetachedSignatures) - Undefined error: 0
xpc_support_check_token: anchor apple error: Error Domain=NSOSStatusErrorDomain Code=-67050 "(null)" status: -67050
I have used codesign -d --verbose=4 /path/to/executable to check the attributes I do get them in the terminal.
Other way round, I have tried XPC service provider sending back process id (pid) with each request, and I am probing this id to get attributes using this code which gives all the details.
func inspectCodeSignature(ofPIDString pidString: String) {
guard let pid = pid_t(pidString) else {
print("Invalid PID string: \(pidString)")
return
}
let attributes = [kSecGuestAttributePid: pid] as CFDictionary
var codeRef: SecCode?
let status = SecCodeCopyGuestWithAttributes(nil, attributes, [], &codeRef)
guard status == errSecSuccess, let code = codeRef else {
print("Failed to get SecCode for PID \(pid) (status: \(status))")
return
}
var staticCode: SecStaticCode?
let staticStatus = SecCodeCopyStaticCode(code, [], &staticCode)
guard staticStatus == errSecSuccess, let staticCodeRef = staticCode else {
print("Failed to get SecStaticCode (status: \(staticStatus))")
return
}
var infoDict: CFDictionary?
if SecCodeCopySigningInformation(staticCodeRef, SecCSFlags(rawValue: kSecCSSigningInformation), &infoDict) == errSecSuccess,
let info = infoDict as? [String: Any] {
print("🔍 Code Signing Info for PID \(pid):")
print("• Identifier: \(info["identifier"] ?? "N/A")")
print("• Team ID: \(info["teamid"] ?? "N/A")")
if let entitlements = info["entitlements-dict"] as? [String: Any] {
print("• Entitlements:")
for (key, value) in entitlements {
print(" - \(key): \(value)")
}
}
} else {
print("Failed to retrieve signing information.")
}
var requirement: SecRequirement?
if SecRequirementCreateWithString("anchor apple" as CFString, [], &requirement) == errSecSuccess,
let req = requirement {
let result = SecStaticCodeCheckValidity(staticCodeRef, [], req)
if result == errSecSuccess {
print("Signature is trusted (anchor apple)")
} else {
print("Signature is NOT trusted by Apple (failed anchor check)")
}
}
var infoDict1: CFDictionary?
let signingStatus = SecCodeCopySigningInformation(staticCodeRef, SecCSFlags(rawValue: kSecCSSigningInformation), &infoDict1)
guard signingStatus == errSecSuccess, let info = infoDict1 as? [String: Any] else {
print("Failed to retrieve signing information.")
return
}
print("🔍 Signing Info for PID \(pid):")
for (key, value) in info.sorted(by: { $0.key < $1.key }) {
print("• \(key): \(value)")
}
}
If connection.setCodeSigningRequirement does not works I plan to use above logic as backup.
Q: Please advise is there some setting required to be enabled or I have to sign code with some flags enabled.
Note: My app is not running in a Sandbox or Hardened Runtime, which I want.
I'm using Secure Enclave to generate and use a private key like this:
let access = SecAccessControlCreateWithFlags(nil,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
[.privateKeyUsage, .biometryAny],
nil)
let attributes: [String: Any] = [
kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeySizeInBits as String: 256,
kSecAttrTokenID as String: kSecAttrTokenIDSecureEnclave,
kSecAttrAccessControl as String: access as Any,
kSecAttrApplicationTag as String: "com.example.key".data(using: .utf8)!,
kSecReturnRef as String: true
]
let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, nil)
Later, I use this key to sign a message:
let signature = SecKeyCreateSignature(privateKey, .ecdsaSignatureMessageX962SHA256, dataToSign as CFData, nil)
This prompts for biometric authentication, but shows the default system text.
How can I customize or localize the biometric prompt (e.g., title, description, button text) shown during SecKeyCreateSignature?
Thanks!
I have been trying to find a way to be able to sign some data with private key of an identity in login keychain without raising any prompts.
I am able to do this with system keychain (obviously with correct permissions and checks) but not with login keychain. It always ends up asking user for their login password.
Here is how the code looks, roughly,
NSDictionary *query = @{
(__bridge id)kSecClass: (__bridge id)kSecClassIdentity,
(__bridge id)kSecReturnRef: @YES,
(__bridge id)kSecMatchLimit: (__bridge id)kSecMatchLimitAll
};
CFTypeRef result = NULL;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&amp;result);
NSArray *identities = ( NSArray *)result;
SecIdentityRef identity = NULL;
for (id _ident in identities) {
// pick one as required
}
SecKeyRef privateKey = NULL;
OSStatus status = SecIdentityCopyPrivateKey(identity, &amp;privateKey);
NSData *strData = [string dataUsingEncoding:NSUTF8StringEncoding];
unsigned char hash[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(strData.bytes, (CC_LONG)strData.length, hash);
NSData *digestData = [NSData dataWithBytes:hash length:CC_SHA256_DIGEST_LENGTH];
CFErrorRef cfError = NULL;
NSData *signature = (__bridge_transfer NSData *)SecKeyCreateSignature(privateKey,
kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256,
(__bridge CFDataRef)digestData,
&amp;cfError);
Above code raises these system logs in console
default 08:44:52.781024+0000 securityd client is valid, proceeding
default 08:44:52.781172+0000 securityd code requirement check failed (-67050), client is not Apple-signed
default 08:44:52.781233+0000 securityd displaying keychain prompt for /Applications/Demo.app(81692)
If the key is in login keychain, is there any way to do SecKeyCreateSignature without raising prompts? What does client is not Apple-signed mean?
PS: Identities are pre-installed either manually or via some device management solution, the application is not installing them.
Hi, We are facing a major issue with our application. We are using FolioReaderkit to read epub files. Currently, it's working on the iOS 18.1 device and simulator, but it's not working on the iOS 18.2 and later version devices.
we are facing this error in Folioreaderkit
Is it possible using the network framework to retrieve the list of certificates presented by the host alone, and not the reconstructed chain assembled by the system?
For example, in OpenSSL one can call SSL_get_peer_cert_chain which will return exactly this - a list of the certificates presented by the server. This is useful for when you may want to manually reconstruct the chain, or if the server is misconfigured (for example, is missing an intermediate cert).
Is something like this possible with the network framework?
If I connect to a host that I know only returns 1 certificate, the trust ref already has the reconstructed chain by the time my code is called:
sec_protocol_options_set_verify_block(tlsOptions.securityProtocolOptions, { metadata, trustRef, verifyComplete in
let trust = sec_trust_copy_ref(trustRef).takeRetainedValue()
let numberOfCertificates = SecTrustGetCertificateCount(trust) // Returns 3 even though the server only sent 1
Hi,
I am creating a custom login window, so I am using SFAuthorizationpluginView, here I want to hide Submit Arrow botton which gets displayed beside username and password text feild
, is there a way to hide this, please suggest.
Hi everyone,
I’ve been working on storing keys and passwords in the macOS Keychain using the Keychain Services API. Specifically, I’m leveraging SecAccessControlCreateWithFlags to bind items to access control flags, and overall, it’s been working smoothly.
I have a question regarding the .applicationPassword flag of SecAccessControlCreateWithFlags. While it successfully prompts the user to input a password, there are no apparent password rules, even a simple “1” is accepted.
My questions are:
Is there a way to enforce strong password requirements when using the .applicationPassword flag?
If enforcing strong passwords isn’t possible, is there an alternative approach to provide a predefined strong password during the creation process, bypassing the need for user input?
With SecAccessControlCreateWithFlags, I noticed the item isn’t stored in the traditional file-based Keychain but in an iOS-style Keychain, is there a way to store it in a file-based Keychain while marking it as unexportable?
I appreciate any insights or suggestions.
Thank you!
Neil
I am developing an Authorisation Plugin which talks to Launch daemons over XPC.
Above is working neat, now I have to decide on how to get it installed on a machine.
Installation requires.
Plugin Installation
Launch Daemon Installation
Both require
Moving binary and text (.plist) file into privileged system managed directory.
Firing install/load commands as root (sudo).
I have referred this post BSD Privilege Escalation on macOS, but I am still not clear how to approach this.
Q: My requirement is:
I can use .pkg builder and install via script, however I have some initialisation task that needs to be performed. User will enter some details talk to a remote server and get some keys, all goes well restarts the system and my authorisation plugin will welcome him and get him started.
If I cannot perform initialisation I will have to do it post restart on login screen which I want to avoid if possible.
I tried unconventional way of using AppleScript from a SwiftUI application to run privileged commands, I am fine if it prompts for admin credentials, but it did not work.
I don't want that I do something and when approving it from Apple it gets rejected.
Basically, how can I provide some GUI to do initialisation during installation or may be an app which helps in this.
Q: Please also guide if I am doing elevated actions, how will it affect app distribution mechanism. In Read Me for EvenBetterAuthorizationSample I read it does.
Thanks.
I am developing a sample authorization plugin to sync the user’s local password to the network password. During the process, I prompt the user to enter both their old and new passwords in custom plugin. After the user enters the information, I use the following code to sync the passwords:
try record.changePassword(oldPssword, toPassword: newPassword)
However, I have noticed that this is clearing all saved keychain information, such as web passwords and certificates. Is it expected behavior for record.changePassword to clear previously stored keychain data?
If so, how can I overcome this issue and ensure the keychain information is preserved while syncing the password?
Thank you for your help!
I have Authorisation Plugin which talks using XPC to my Launch Daemon to perform privileged actions.
I want to protect my XPC service narrowing it to be called from known trusted clients.
Now since I want authorisation plugin code which is from apple to call my service, I cannot use my own team id or app group here.
I am currently banking on following properties of client connection.
Apple Team ID : EQHXZ8M8AV
Bundle ID starting with com.apple.
Client signature verified By Apple.
This is what I have come up with.
func isClientTrusted(connection: NSXPCConnection) -> Bool {
let clientPID = connection.processIdentifier
logInfo("🔍 Checking XPC Client - PID: \(clientPID)")
var secCode: SecCode?
var secStaticCode: SecStaticCode?
let attributes = [kSecGuestAttributePid: clientPID] as NSDictionary
let status = SecCodeCopyGuestWithAttributes(nil, attributes, [], &secCode)
guard status == errSecSuccess, let code = secCode else {
logInfo("Failed to get SecCode for PID \(clientPID)")
return false
}
let staticStatus = SecCodeCopyStaticCode(code, [], &secStaticCode)
guard staticStatus == errSecSuccess, let staticCode = secStaticCode else {
logInfo("Failed to get SecStaticCode")
return false
}
var signingInfo: CFDictionary?
let signingStatus = SecCodeCopySigningInformation(staticCode, SecCSFlags(rawValue: kSecCSSigningInformation), &signingInfo)
guard signingStatus == errSecSuccess, let info = signingInfo as? [String: Any] else {
logInfo("Failed to retrieve signing info")
return false
}
// Extract and Verify Team ID
if let teamID = info["teamid"] as? String {
logInfo("XPC Client Team ID: \(teamID)")
if teamID != "EQHXZ8M8AV" { // Apple's official Team ID
logInfo("Client is NOT signed by Apple")
return false
}
} else {
logInfo("Failed to retrieve Team ID")
return false
}
// Verify Bundle ID Starts with "com.apple."
if let bundleID = info["identifier"] as? String {
logInfo("XPC Client Bundle ID: \(bundleID)")
if !bundleID.hasPrefix("com.apple.") {
logInfo("Client is NOT an Apple system process")
return false
}
} else {
logInfo("Failed to retrieve Bundle Identifier")
return false
}
// Verify Apple Code Signature Trust
var trustRequirement: SecRequirement?
let trustStatus = SecRequirementCreateWithString("anchor apple" as CFString, [], &trustRequirement)
guard trustStatus == errSecSuccess, let trust = trustRequirement else {
logInfo("Failed to create trust requirement")
return false
}
let verifyStatus = SecStaticCodeCheckValidity(staticCode, [], trust)
if verifyStatus != errSecSuccess {
logInfo("Client's signature is NOT trusted by Apple")
return false
}
logInfo("Client is fully verified as Apple-trusted")
return true
}
Q: Just wanted community feedback, is this correct approach?
I created a self signed CA and use it to generate/sign a client cert using openssl. Then I use the self signed client cert to do TLS client authentication with my server (which also uses the self signed CA). The issue I have is when I validate the self signed CA, by calling SecTrustEvaluateAsyncWithError, it always complains this error “'DigiCert Global Root G3' certificate is not trusted". However that CA (DigiCert Global Root G3) is not my self signed CA (my CA is 'MQTTSampleCA' and I attached a dump of the my CA cert in the PR in the end of this post), so I'm confused why the API keeps complaining that CA. After some researching, I see that is a well known CA so I download its cert from https://www.digicert.com/kb/digicert-root-certificates.htm, install and trust it on my iOS device, but that doesn't help and I still get the same error. I provide all the repro steps in this PR: https://github.com/liumiaojq/EmCuTeeTee/pull/1, including how I generate the certs and the source codes of a test app that I used to do cert validation. I appreciate if anyone can share insights how to resolve this error.
I am developing a MacOS Authorisation Plugin, I have username and password entry items and utilising SFAuthorizationPluginView to display that. I am able to do so.
Requirement is I have to store ed25519 private key in PEM format in System Keychain as I need to read this entry before login to sign a request to a remote server.
I only want my authorisation plugin to access this private key in System Keychain.
I am looking up resources on the internet but I could not find specific to macOS Authorisation plugin, many are specific to iOS and some point at using entitlements and app group, but I doubt that applies to macOS authorisation plugin.
I'll really appreciate if some pointers are shared how can I store a private credential in System Keychain so that it can be used by only my plugin only, and this is before I have logged into the system.
I am developing an Authorization plugin for macOS that should be invoked when a user unlocks their device from the lock screen. Based on advice from the other threads in these forums, I have understood that:
The plugin needs to use SFAuthorizationPluginView
The auth db entries to modify are system.login.screensaver and authenticate
I found the NameAndPassword sample and after making some tweaks to it was able to get it to work from screensaver unlock.
I am trying to add Webview-based authentication to the plugin, but have not had any success. The plugin window's width does not change (though the height does) and only a small portion of the HTML gets rendered. Is Webview-based authentication supported with SFAuthorizationPluginView? Are there any alternatives?