General:
Apple Platform Security support document
Security Overview
Cryptography:
DevForums tags: Security, Apple CryptoKit
Security framework documentation
Apple CryptoKit framework documentation
Common Crypto man pages — For the full list of pages, run:
% man -k 3cc
For more information about man pages, see Reading UNIX Manual Pages.
On Cryptographic Key Formats DevForums post
SecItem attributes for keys DevForums post
CryptoCompatibility sample code
Keychain:
DevForums tags: Security
Security > Keychain Items documentation
TN3137 On Mac keychain APIs and implementations
SecItem Fundamentals DevForums post
SecItem Pitfalls and Best Practices DevForums post
Investigating hard-to-reproduce keychain problems DevForums post
Smart cards and other secure tokens:
DevForums tag: CryptoTokenKit
CryptoTokenKit framework documentation
Mac-specific frameworks:
DevForums tags: Security Foundation, Security Interface
Security Foundation framework documentation
Security Interface framework documentation
Related:
Networking Resources — This covers high-level network security, including HTTPS and TLS.
Network Extension Resources — This covers low-level network security, including VPN and content filters.
Code Signing Resources
Notarisation Resources
Trusted Execution Resources — This includes Gatekeeper.
App Sandbox Resources
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Security
RSS for tagSecure the data your app manages and control access to your app using the Security framework.
Posts under Security tag
200 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
I regularly help developers with keychain problems, both here on DevForums and for my Day Job™ in DTS. Many of these problems are caused by a fundamental misunderstanding of how the keychain works. This post is my attempt to explain that. I wrote it primarily so that Future Quinn™ can direct folks here rather than explain everything from scratch (-:
If you have questions or comments about any of this, put them in a new thread and apply the Security tag so that I see it.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
SecItem: Fundamentals
or How I Learned to Stop Worrying and Love the SecItem API
The SecItem API seems very simple. After all, it only has four function calls, how hard can it be? In reality, things are not that easy. Various factors contribute to making this API much trickier than it might seem at first glance.
This post explains the fundamental underpinnings of the keychain. For information about specific issues, see its companion post, SecItem: Pitfalls and Best Practices.
Keychain Documentation
Your basic starting point should be Keychain Items.
If your code runs on the Mac, also read TN3137 On Mac keychain APIs and implementations.
Read the doc comments in <Security/SecItem.h>. In many cases those doc comments contain critical tidbits.
When you read keychain documentation [1] and doc comments, keep in mind that statements specific to iOS typically apply to iPadOS, tvOS, and watchOS as well (r. 102786959). Also, they typically apply to macOS when you target the data protection keychain. Conversely, statements specific to macOS may not apply when you target the data protection keychain.
[1] Except TN3137, which is very clear about this (-:
Caveat Mac Developer
macOS supports two different implementations: the original file-based keychain and the iOS-style data protection keychain. If you’re able to use the data protection keychain, do so. It’ll make your life easier.
TN3137 On Mac keychain APIs and implementations explains this distinction in depth.
The Four Freedoms^H^H^H^H^H^H^H^H Functions
The SecItem API contains just four functions:
SecItemAdd(_:_:)
SecItemCopyMatching(_:_:)
SecItemUpdate(_:_:)
SecItemDelete(_:)
These directly map to standard SQL database operations:
SecItemAdd(_:_:) maps to INSERT.
SecItemCopyMatching(_:_:) maps to SELECT.
SecItemUpdate(_:_:) maps to UPDATE.
SecItemDelete(_:) maps to DELETE.
You can think of each keychain item class (generic password, certificate, and so on) as a separate SQL table within the database. The rows of that table are the individual keychain items for that class and the columns are the attributes of those items.
Note Except for the digital identity class, kSecClassIdentity, where the values are split across the certificate and key tables. See Digital Identities Aren’t Real in SecItem: Pitfalls and Best Practices.
This is not an accident. The data protection keychain is actually implemented as an SQLite database. If you’re curious about its structure, examine it on the Mac by pointing your favourite SQLite inspection tool — for example, the sqlite3 command-line tool — at the keychain database in ~/Library/Keychains/UUU/keychain-2.db, where UUU is a UUID.
WARNING Do not depend on the location and structure of this file. These have changed in the past and are likely to change again in the future. If you embed knowledge of them into a shipping product, it’s likely that your product will have binary compatibility problems at some point in the future. The only reason I’m mentioning them here is because I find it helpful to poke around in the file to get a better understanding of how the API works.
For information about which attributes are supported by each keychain item class — that is, what columns are in each table — see the Note box at the top of Item Attribute Keys and Values. Alternatively, look at the Attribute Key Constants doc comment in <Security/SecItem.h>.
Uniqueness
A critical part of the keychain model is uniqueness. How does the keychain determine if item A is the same as item B? It turns out that this is class dependent. For each keychain item class there is a set of attributes that form the uniqueness constraint for items of that class. That is, if you try to add item A where all of its attributes are the same as item B, the add fails with errSecDuplicateItem. For more information, see the errSecDuplicateItem page. It has lists of attributes that make up this uniqueness constraint, one for each class.
These uniqueness constraints are a major source of confusion, as discussed in the Queries and the Uniqueness Constraints section of SecItem: Pitfalls and Best Practices.
Parameter Blocks Understanding
The SecItem API is a classic ‘parameter block’ API. All of its inputs are dictionaries, and you have to know which properties to set in each dictionary to achieve your desired result. Likewise for when you read properties in output dictionaries.
There are five different property groups:
The item class property, kSecClass, determines the class of item you’re operating on: kSecClassGenericPassword, kSecClassCertificate, and so on.
The item attribute properties, like kSecAttrAccessGroup, map directly to keychain item attributes.
The search properties, like kSecMatchLimit, control how the system runs a query.
The return type properties, like kSecReturnAttributes, determine what values the query returns.
The value type properties, like kSecValueRef perform multiple duties, as explained below.
There are other properties that perform a variety of specific functions. For example, kSecUseDataProtectionKeychain tells macOS to use the data protection keychain instead of the file-based keychain. These properties are hard to describe in general; for the details, see the documentation for each such property.
Inputs
Each of the four SecItem functions take dictionary input parameters of the same type, CFDictionary, but these dictionaries are not the same. Different dictionaries support different property groups:
The first parameter of SecItemAdd(_:_:) is an add dictionary. It supports all property groups except the search properties.
The first parameter of SecItemCopyMatching(_:_:) is a query and return dictionary. It supports all property groups.
The first parameter of SecItemUpdate(_:_:) is a pure query dictionary. It supports all property groups except the return type properties.
Likewise for the only parameter of SecItemDelete(_:).
The second parameter of SecItemUpdate(_:_:) is an update dictionary. It supports the item attribute and value type property groups.
Outputs
Two of the SecItem functions, SecItemAdd(_:_:) and SecItemCopyMatching(_:_:), return values. These output parameters are of type CFTypeRef because the type of value you get back depends on the return type properties you supply in the input dictionary:
If you supply a single return type property, except kSecReturnAttributes, you get back a value appropriate for that return type.
If you supply multiple return type properties or kSecReturnAttributes, you get back a dictionary. This supports the item attribute and value type property groups. To get a non-attribute value from this dictionary, use the value type property that corresponds to its return type property. For example, if you set kSecReturnPersistentRef in the input dictionary, use kSecValuePersistentRef to get the persistent reference from the output dictionary.
In the single item case, the type of value you get back depends on the return type property and the keychain item class:
For kSecReturnData you get back the keychain item’s data. This makes most sense for password items, where the data holds the password. It also works for certificate items, where you get back the DER-encoded certificate. Using this for key items is kinda sketchy. If you want to export a key, called SecKeyCopyExternalRepresentation. Using this for digital identity items is nonsensical.
For kSecReturnRef you get back an object reference. This only works for keychain item classes that have an object representation, namely certificates, keys, and digital identities. You get back a SecCertificate, a SecKey, or a SecIdentity, respectively.
For kSecReturnPersistentRef you get back a data value that holds the persistent reference.
Value Type Subtleties
There are three properties in the value type property group:
kSecValueData
kSecValueRef
kSecValuePersistentRef
Their semantics vary based on the dictionary type.
For kSecValueData:
In an add dictionary, this is the value of the item to add. For example, when adding a generic password item (kSecClassGenericPassword), the value of this key is a Data value containing the password.
This is not supported in a query dictionary.
In an update dictionary, this is the new value for the item.
For kSecValueRef:
In add and query dictionaries, the system infers the class property and attribute properties from the supplied object. For example, if you supply a certificate object (SecCertificate, created using SecCertificateCreateWithData), the system will infer a kSecClass value of kSecClassCertificate and various attribute values, like kSecAttrSerialNumber, from that certificate object.
This is not supported in an update dictionary.
For kSecValuePersistentRef:
For query dictionaries, this uniquely identifies the item to operate on.
This is not supported in add and update dictionaries.
Revision History
2023-09-12 Fixed various bugs in the revision history. Added a paragraph explaining how to determine which attributes are supported by each keychain item class.
2023-02-22 Made minor editorial changes.
2023-01-28 First posted.
I am trying to generate public and private keys for an ECDH handshake.
Back end is using p256 for public key. I am getting a failed request with status 0
public func makeHandShake(completion: @escaping (Bool, String?) -> ()) {
guard let config = self.config else { completion(false,APP_CONFIG_ERROR)
return
}
var rData = HandshakeRequestTwo()
let sessionValue = AppUtils().generateSessionID()
rData.session = sessionValue
//generating my ECDH Key Pair
let sPrivateKey = P256.KeyAgreement.PrivateKey()
let sPublicKey = sPrivateKey.publicKey
let privateKeyBase64 = sPrivateKey.rawRepresentation.base64EncodedString()
print("My Private Key (Base64): \(privateKeyBase64)")
let publicKeyBase64 = sPublicKey.rawRepresentation.base64EncodedString()
print("My Public Key (Base64): \(publicKeyBase64)")
rData.value = sPublicKey.rawRepresentation.base64EncodedString()
let encoder = JSONEncoder()
do {
let jsonData = try encoder.encode(rData)
if let jsonString = String(data: jsonData, encoding: .utf8) {
print("Request Payload: \(jsonString)")
}
} catch {
print("Error encoding request model to JSON: \(error)")
completion(false, "Error encoding request model")
return
}
self.rsaReqResponseHandler(config: config, endpoint: config.services.handShake.endpoint, model: rData) { resToDecode, error in
print("Response received before guard : \(resToDecode ?? "No response")")
guard let responseString = resToDecode else {
print("response string is nil")
completion(false,error)
return
}
print("response received: \(responseString)")
let decoder = JSONDecoder()
do {
let request = try decoder.decode(DefaultResponseTwo.self, from: Data(responseString.utf8))
let msg = request.message
let status = request.status == 1 ? true : false
completion(status,msg)
guard let serverPublicKeyBase64 = request.data?.value else {
print("Server response is missing the value")
completion(false, config.messages.serviceError)
return
}
print("Server Public Key (Base64): \(serverPublicKeyBase64)")
if serverPublicKeyBase64.isEmpty {
print("Server public key is an empty string.")
completion(false, config.messages.serviceError)
return
}
guard let serverPublicKeyData = Data(base64Encoded: serverPublicKeyBase64) else {
print("Failed to decode server public key from Base64. Data is invalid.")
completion(false, config.messages.serviceError)
return
}
print("Decoded server public key data: \(serverPublicKeyData)")
guard let serverPublicKey = try? P256.KeyAgreement.PublicKey(rawRepresentation: serverPublicKeyData) else {
print("Decoded server public key data is invalid for P-256 format.")
completion(false, config.messages.serviceError)
return
}
// Derive Shared Secret and AES Key
let sSharedSecret = try sPrivateKey.sharedSecretFromKeyAgreement(with: serverPublicKey)
// Derive AES Key from Shared Secret
let symmetricKey = sSharedSecret.hkdfDerivedSymmetricKey(
using: SHA256.self,
salt: "AES".data(using: .utf8) ?? Data(),
sharedInfo: Data(),
outputByteCount: 32
)
// Storing AES Key in Config
let symmetricKeyBase64 = symmetricKey.withUnsafeBytes { Data($0) }.base64EncodedString()
print("Derived Key: \(symmetricKeyBase64)")
self.config?.cryptoConfig.key = symmetricKeyBase64
AppUtils.Log(from: self, with: "Handshake Successful, AES Key Established")
} catch {
AppUtils.Log(from: self, with: "Handshake Failed :: \(error)")
completion(false, self.config?.messages.serviceError)
}
}
} this is request struct model public struct HandshakeRequestTwo: Codable {
public var session: String?
public var value: String?
public enum CodingKeys: CodingKey {
case session
case value
}
public init(session: String? = nil, value: String? = nil) {
self.session = session
self.value = value
}
} This is backend's response {"message":"Success","status":1,"data":{"senderId":"POSTBANK","value":"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAErLxbfQzX+xnYVT1LLP5VOKtkMRVPRCoqYHcCRTM64EMEOaRU16yzsN+2PZMJc0HpdKNegJQZMmswZtg6U9JGVw=="}} This is my response struct model public struct DefaultResponseTwo: Codable {
public var message: String?
public var status: Int?
public var data: HandshakeData?
public init(message: String? = nil, status: Int? = nil, data: HandshakeData? = nil) {
self.message = message
self.status = status
self.data = data
}
}
public struct HandshakeData: Codable {
public var senderId: String?
public var value: String?
public init(senderId: String? = nil, value: String? = nil) {
self.senderId = senderId
self.value = value
}
}
Hi everyone,
I’m currently developing an MFA authorization plugin for macOS and am looking to implement a passwordless feature. The goal is to store the user's password securely when they log into the system through the authorization plugin.
However, I’m facing an issue with using the system's login keychain (Data Protection Keychain), as it runs in the user context, which isn’t suitable for my case. Therefore, I need to store the password in a file-based keychain instead.
Does anyone have experience or code snippets for objective-c for securely storing passwords in a file-based keychain (outside of the login keychain) on macOS? Specifically, I'm looking for a solution that would work within the context of a system-level authorization plugin.
Any advice or sample code would be greatly appreciated!
Thanks in advance!
Hi,
I need a version of a web app to be accessible on a local network (LAN), when the users connect to a wifi without internet access.
I provide a valid TLS certificate to validate the website. There is also a local DNS (dnsmasq), with the following entries to return NXDOMAIN, as specified by the documentation.
server=/mask.icloud.com/
server=/mask-h2.icloud.com/
However, without internet (no cellular data), there is an error in Safari instead of the website. When there is some internet connection, there is a warning that allows to continue to the website by showing the IP address, which is not clear for the user.
iPhone users are very frustrated. Is there a solution?
Is there a way to know the event of user unlocking on iOS Device in Application?
Hi everyone,
I'm working on a macOS authorization plugin (NameAndPassword) to enable users to log into their system using only MFA, effectively making it passwordless. To achieve this, I'm attempting to store the user's password securely in the Keychain so it can be used when necessary without user input.
However, when I attempt to store the password, I encounter error code -25308. Below is the code I'm using to save the password to the Keychain:
objc code
(void)storePasswordInKeychain:(NSString *)password forAccount:(NSString *)accountName {
NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *query = @{
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService: @"com.miniOrange.nameandpassword",
(__bridge id)kSecAttrAccount: accountName,
(__bridge id)kSecValueData: passwordData,
(__bridge id)kSecAttrAccessible: (__bridge id)kSecAttrAccessibleAfterFirstUnlock
};
// Delete any existing password for the account
OSStatus deleteStatus = SecItemDelete((__bridge CFDictionaryRef)query);
if (deleteStatus == errSecSuccess || deleteStatus == errSecItemNotFound) {
[Logger debug:@"Old password entry deleted or not found."];
} else {
[Logger error:@"Failed to delete existing password: %d", (int)deleteStatus];
}
// Add the new password
OSStatus addStatus = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
if (addStatus == errSecSuccess) {
[Logger debug:@"Password successfully saved to the Keychain."];
} else {
[Logger error:@"Failed to save password: %d", (int)addStatus];
}
}
Any insights or suggestions would be greatly appreciated!
Hi,
I have a SAML authentication scenario with MFA(probably Okta) in my app that runs in WKWebView using Cordova. I am currently doing POC to authenticate PIV certificates(either one of the 3 Issuers: DISA Purebred, Intercede and Entrust) in WKWebView with Cordova.
As if now, I have found that WKNavigationDelegate method: didReceive challenge, we can authenticate the certificate. Also, these PIV certificates which are stored in the form of .p12 in Apple's keychain group needs to be imported using function: SecPKCS12Import.
Please let me know if my understanding is correct or if there are any implementation challenges in WKWebView with Cordova.
I would highly appreciate if any information regarding this can be provided.
Hi there, I'm currently working on a compatibility feature for Apple that allows the user to manage their keys and certificates from within our internal API. For this I need to retrieve all the items contained within keychains.
I am looking at the documentation for SecItem API but so far I have not really found an obvious way to link these items together. My best guess so far is to perform two queries, grabbing all SecKeys from the keychains, pairing them up with public keys through SecKeyCopyPublicKey, then downloading all CertItems and pairing them with public keys with SecCertificateCopyKey, and then join the two using public keys.
This sounds however somewhat involved and I was wondering if there was a better way of going about the process?
In our application, we store user information (Username, Password, accessToken, Refresh token, etc.) in the keychain. However, after performing a hard reboot (unplugging and plugging back in), when we attempt to retrieve the ‘refresh token’ or ‘access token’ from the keychain, we receive the old token instead of the newly saved one.
I'm using this library for encoding / decoding RSA keys. https://github.com/Kitura/BlueRSA
It's worked fine up until macOS sequoia. The issue I'm having is the tests pass when in Debug mode, but the moment I switch to Release mode, the library no longer works.
I ruled this down the swift optimization level.
If I change the Release mode to no optimization, the library works again. Wondering where in the code this could be an issue? How would optimization break the functionality?
I am getting issue on my application that my device is jailbroken security message I updated my device 18.2 what the solution
Hi there,
I have a Multiplatform app with just one app target with an iPhone, iPad and Мас Destination. On the Mac my app is a developer singed App that is being distributed outside of the Mac App Store.
I want to use App Groups, but as long as there are multiple destinations, Xcode only allows Group Identifiers starting with group.. However, for macOS I need to have a group ID that starts with the TeamID as explained here.
So I created two separate entitlements, which are identical, but with different group IDs:
With Automatic Code Signing enabled, I get this warning:
Xcode still seems thinks it has to use the macOS Group ID for the iOS version. In the App Groups section, the mac Group ID is red and the iOS Group ID is not checked.
The app builds and runs without issues on all platforms. The App Store Connect validation (for the iOS version) also works without any errors.
Am I doing something wrong? Do I need a separate Mac target because Xcode does not support separate Group IDs for Multiplatform apps?
Since this file is protected by SIP, it can't just be changed by an installer/app without prompting the user. If the user chooses to deny the request, the sudo file won't be updated with a security critical pam module.
I need to insert our custom pam module into /etc/pam.d/sudo without the user being able to deny the operation.
Hi,
I have recently encountered an app with some odd behaviour and wanted to clarify some details about the way sandboxing works with iOS apps installed on a Mac. I am unsure whether this is due to a misunderstanding of system behaviour or whether this is a bug.
The app was installed from the Mac App Store, designed for iPad.
The developer of the app informed me that in lieu of a sign-in process, the app tries to persistently store a UUID of the user on the device so that when the app is deleted and reinstalled, the user is automatically logged in again.
The developer says that two mechanisms are being used: 1) NSUserDefaults (via Flutter shared prefs) and 2) identifierForVendor.
In the case of 1), my understanding is that these are managed by cfprefsd. Using the 'defaults domain' command, the domain of the app appears. However, there are no keys or values stored. Using the 'defaults write' and 'defaults read' and 'defaults delete' commands on that bundle identifier works as expected, but since it starts out empty, it cannot be read or deleted.
Furthermore, the app's data is supposed to be sandboxed in /Library/Containers. When the app is uninstalled from Launchpad, I have confirmed that the folder is missing. When reinstalled, the app's settings and data are missing, but crucially, the cloud identifier is still persistent and is evident after 'setup'.
In the case of 2), the developer documentation states that identifierForVendor changes when all apps from a developer have been removed from a device. The app in question is the only app that was installed from this developer, so logically this identifier should have changed when the app was deleted and reinstalled.
I have confirmed that iCloud drive is not being used to store this data as there is no data in iCloud for this app.
In any case, when the app is uninstalled and reinstalled, the app automatically logs the user into the "account" it was previously logged into, along with all of that user's data in the cloud.
I have a sense that this type of persistent identifier tracking is what sandboxing was meant to address, but I am unsure why I have been unable to remove the UUID tag from my system. Any insight would be greatly appreciated!
We are using device certificates for authentication when logging into our web page. After updating an iPhone 12 to iOS 18, the authentication process takes up to two minutes to respond.
Upon investigating IIS, it was found that the certificate is not being presented from the iPhone, resulting in a timeout.
This issue is affecting our operations, and we need a solution urgently.
Could you please advise on how to resolve this?
I generate a keys using :
let attributes: NSDictionary = [
kSecAttrLabel: label,
kSecUseKeychain: getSystemKeychain()!,
kSecAttrKeyType: kSecAttrKeyTypeEC,
kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeySizeInBits: 256,
kSecPrivateKeyAttrs: [
kSecAttrIsPermanent: true,
kSecAttrApplicationTag: tag,
] as [CFString : Any]
]
var error: Unmanaged<CFError>?
// Generate a new private key
guard let privateKey = SecKeyCreateRandomKey(attributes, &error) else {
logger.error("failed to create a keypair \(String(describing: error))")
return (nil, nil)
}
I keep getting this error :
failed to create a keypair Optional(Swift.Unmanaged<__C.CFErrorRef>(_value: Error Domain=NSOSStatusErrorDomain Code=-2070 "internal error" (internalComponentErr) UserInfo={numberOfErrorsDeep=0, NSDescription=internal error}))
The above code works absolutely fine on macOS Sonoma and older OS. This looks like a regression in the Apple API SecKeyCreateRandomKey(). What is a good workaround for this ?
We currently are using private web security certificates for our URLs. Our users download, install, and enable a Root Certificate on their devices to reach our website (trusted). The web security certificates have expirations that are less than 13 months from expiration.
Since the deployment of iOS 18, our users are now getting a "This Connection is not Private" warning in the web browser on both Mac and iOS devices.
What change was implemented in iOS 18 that is causing this issue? Other than changing our web security certificates to Public ones, what solutions should be implemented to prevent this from occurring?
I have implemented SSL pinning by following this article https://developer.apple.com/news/?id=g9ejcf8y , however pen testing team was able to bypass SSL pinning using Objection & Frida tools.
I am using URLSession for API calls. I used Xcode 16. My app's minimum iOS deployment version is 16 onwards.
<key>NSAppTransportSecurity</key>
<dict>
<key>NSPinnedDomains</key>
<dict>
<key>*.mydomain.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSPinnedCAIdentities</key>
<array>
<dict>
<key>SPKI-SHA256-BASE64</key>
<string>my SHA256 key</string>
</dict>
</array>
</dict>
</dict>
</dict>
Could anyone suggest how to mitigate this bypass mechanism?
Wake up this morning and see this very concerning sticky message in Notification Center:
bash was prevented from modifying apps
It didn't say what parent program called `bash' so I clicked on the N.C. message to see if there was more information and it just disappeared (as if I had chosen to click on the X to clear the message-I wish I had taken a screenshot first). I have already sent in a request to Apple for them to give more detailed information on events like this. If there is an existing threat on a device it needs to be removed.
The only thing that I know of that happened overnight was a SPAM email from "Norton Antivirus" came into my Gmail Inbox that wasn't filtered as SPAM and macOS announced it in Notification Center. I don't see anything funny in the RAW data of the email - and reported it to spamcop.
Is it possible that a malicious email could contain html code that runs when it's announced via macOS Notification Center?
Hello,
I have a system, which is able to execute bash/zsh scripts on a set of machines.
The default behaviour is that the signature of the script is checked on the machine, which is executing it, and in case if it is not signed properly, the system rejects the execution.
An own certificate has to be created for signing the scripts, which means that the certificate has to be installed and marked as trusted on the target machines (which are executing the script).
I've been using :
"/usr/bin/security add-trusted-cert ..."
command to install the certificate on the machines as trusted.
Since macOS Big Sur, the above command was prompting the local user for admin credentials. To avoid this, Apple suggested to use the following command to temporarily disable and re-enable the confirmation dialog :
1.:
/usr/bin/security authorizationdb write com.apple.trust-settings.admin allow
2.:
/usr/bin/security authorizationdb write com.apple.trust-settings.admin admin
Now with the release of macOS Sequoia, the above command :
"/usr/bin/security authorizationdb write com.apple.trust-settings.admin allow"
does not work any more.
It gives the following output :
NO (-60005)
I have the following questions :
1.: Could you please suggest an alternative way for IT administrators to install certificates on their machines, without any user confirmation?
2.: Could you please suggest how the same could be achieved using a bash/zsh script? In which context could the above commands :
"/usr/bin/security authorizationdb write com.apple.trust-settings.admin allow"
and
"/usr/bin/security authorizationdb write com.apple.trust-settings.admin admin"
still work?
Thank you for your help in advance!
Option 1: Kurz und prägnant
"Hilfe in jeder Situation! Unsere App alarmiert schnell und unkompliziert die Rettungskräfte. Egal wo du bist, wir helfen dir in Notfällen."
Option 2: Detaillierter
"Schnelle Hilfe für alle! Mit unserer App hast du rund um die Uhr einen zuverlässigen Helfer an deiner Seite. Ob du selbst in Not bist oder Zeugen eines Unfalls werden – mit nur einem Klick alarmierst du die Rettungskräfte und erhältst wichtige Informationen. Funktioniert für iOS und Android."
Option 3: Fokus auf die Zielgruppe "Alle"
"Für jeden ein Lebensretter! Egal, ob jung oder alt, sportlich oder weniger beweglich – unsere App ist für alle gedacht, die in einer Notlage schnell Hilfe benötigen. Einfach, intuitiv und immer für dich da."
Option 4: Betonung der Notfallfunktion
"Dein persönlicher Notfallhelfer! In kritischen Situationen zählt jede Sekunde. Unsere App sorgt dafür, dass die Rettungskräfte schnellstmöglich bei dir sind. Perfekt für unterwegs, zu Hause oder am Arbeitsplatz."
Option 5: Hervorhebung der Plattformunabhängigkeit
"Hilfe ohne Grenzen! Unsere App ist für iOS und Android Geräte verfügbar und sorgt dafür, dass du immer und überall Hilfe bekommst. Egal, welches Smartphone du hast, wir sind für dich da."
Möchtest du, dass ich einen Text entwerfe, der alle deine Punkte vereint? Oder hast du weitere Wünsche oder Vorstellungen?