Code Signing

RSS for tag

Certify that an app was created by you using Code signing, a macOS security technology.

Code Signing Documentation

Pinned Posts

Posts under Code Signing tag

260 Posts
Sort by:
Post marked as solved
2 Replies
242 Views
Hi, I created a widget for our application. The application is manually signed for distribution. I created a new identifier and provisioning profile for distribution for the widget. The new identifier is our app identifier with ".widget" appended. After I added both the app and widget provisioning profiles to my export.plist for the xcodebuild step, the app builds without error. When I try to validate the app before upload, I get this error: Error: Invalid Signature. Code object is not signed at all. The file at path [MyApp.app/PlugIns/MyAppWidget.appex/fix_imports.sh] is not properly signed. Make sure you have signed your application with a distribution certificate, not an ad hoc certificate or a development certificate. The provisioning profiles in the export.plist are for distribution. Has anyone else encountered and fixed error? I'm stumped! Claire
Posted
by
Post not yet marked as solved
0 Replies
131 Views
I thought some folks on this forum might find it useful, so I'm sharing that I've just open sourced a Swift package called Required which parses and evaluates requirements written in Apple's Code Signing Requirement Language. Amongst other uses, this package can be quite useful in debugging security requirements used to secure XPC communications. This package only uses public APIs and supports OS X 10.10 and later. (The parser itself has no platform dependencies at all and could in theory be run on any platform Swift supports.) As an example of how the package works, to see whether and how an application satisfies its designated requirement: // Retrieve the designated requirement for Numbers let url = URL(fileURLWithPath: "/Applications/Numbers.app") var code: SecStaticCode? SecStaticCodeCreateWithPath(url as CFURL, [], &code) var requirement: SecRequirement? SecCodeCopyDesignatedRequirement(code!, [], &requirement) // See whether and how Numbers satisifies its designated requirement let abstractRequirement = try Parser.parse(requirement: requirement!) let evaluation = try abstractRequirement.evaluateForStaticCode(code!) print("Does \(url.lastPathComponent) satisfy its designated requirement?") print(evaluation.isSatisfied ? "Yes" : "No") print("\nEvaluation tree:") print(evaluation.prettyDescription) Which outputs: Does Numbers.app satisfy its designated requirement? Yes Evaluation tree: and {true} |--() {true} | \--or {true} | |--and {true} | | |--anchor apple generic {true} | | \--certificate leaf[field.1.2.840.113635.100.6.1.9] {true} | \--and {false} | |--and {false} | | |--and {false} | | | |--anchor apple generic {true} | | | \--certificate 1[field.1.2.840.113635.100.6.2.6] {false}¹ | | \--certificate leaf[field.1.2.840.113635.100.6.1.13] {false}² | \--certificate leaf[subject.OU] = K36BKF7T3D {false}³ \--identifier "com.apple.iWork.Numbers" {true} Constraints not satisfied: 1. The certificate <Apple Worldwide Developer Relations Certification Authority> does not contain OID 1.2.840.113635.100.6.2.6 2. The certificate <Apple Mac OS Application Signing> does not contain OID 1.2.840.113635.100.6.1.13 3. The certificate <Apple Mac OS Application Signing> does not contain element subject.OU
Posted
by
Post not yet marked as solved
0 Replies
81 Views
This post is part of a cluster of posts related to the trusted execution system. If you found your way here directly, I recommend that you start at the top. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Resolving Hardened Runtime Incompatibilities The hardened runtime enables a number of security checks within a process. Some coding techniques are incompatible with the hardened runtime. Best practice is to enable the hardened runtime on all code so that you uncover these problems early. However, some folks only notice these problems when they go to distribute their product. Specifically, Developer ID distribution requires notarisation and the notary service requires the hardened runtime. The typical symptoms of this failure is that the program launches but then fails almost immediately afterwards. Sometimes this failure results in the program just not working, sometimes it triggers a crash, and sometimes the program terminates itself by calling exit. In some cases this failure is accompanied by diagnostic printed to stdout, so it’s worth running the program from Terminal if you can. For advice on how to do that, see Resolving Trusted Execution Problems. If you suspect that this problem is caused by a hardened runtime incompatibility, the diagnostic test is easy: Temporarily disable the hardened runtime and see if the problem goes away. Once you’ve confirmed the problem is an incompatibility with the hardened runtime, you have two choices: Fix your code to avoid the problem. Apply a hardened runtime exception entitlement to disable one specific security feature of the hardened runtime. In general, the first option is best because it leaves your product with the best security. IMPORTANT When confronted by a hardened runtime incompatibility, some folks apply all of the hardened runtime exception entitlements. This is a mistake for three reasons: Some entitlements are subsets of other entitlements. For example, there’s no point applying com.apple.security.cs.allow-unsigned-executable-memory if you’re already applying com.apple.security.cs.disable-executable-page-protection. Disabling library validation with the com.apple.security.cs.disable-library-validation entitlement makes it harder to pass Gatekeeper. For more on this, see Resolving Gatekeeper Problems Caused by Dangling Load Command Paths. The hardened runtime exists for a reason: To enhance your product’s security. Don’t apply a hardened runtime exception entitlement without first understanding what the actual problem is. Debug hardened runtime incompatibilities like you would any other problem: Step through the code, add logging, and so on. The goal is to isolate which part of your code works with the hardened runtime disabled but fails with it enabled. Once you’ve found that code, the fix is usually pretty obvious. For example, if your program needs to generate executable code on the fly, you must: Allocate that memory using mmap with the MAP_JIT flag. Write to that memory using pthread_jit_write_protect_np or one of its related APIs. See the pthread_jit_write_protect_np man page for details. Sign the problem with the com.apple.security.cs.allow-jit entitlement. If you need help with this, feel free to ask here on DevForums. If you don’t control the code that has the hardened runtime incompatibility — this happens most often when using a third-party language runtime — ask the vendor how to proceed. They might have an updated version of their code, or specific advice on what hardened runtime exception entitlements to apply. If their advice is “Apply all the hardened runtime exception entitlements!”, think carefully about your vendor choices (-:
Posted
by
Post not yet marked as solved
1 Replies
145 Views
I tried to codesign my app by following way, we downloaded the certificate from apple developer account and We tried to sign the binaries with the downloaded certificate using codesign command . line command (sudo codesign -f -vv -o runtime --deep --timestamp -s  "Developer Id Cer: user(123455)" try.dylib) I have received the following error Though I have added the certificate in keychain access and also checked that the certificate is valid, I still got**”The specified item could  not be found in the keychain”** . Then I tried same scenario with other certificate but got following error                               Warning: unable to build chain tp self-signed root for signer "Developer Id Cer: user(123456)”                                   try.dylib: errSecInternalComponent Any help would be really appreciated
Posted
by
Post not yet marked as solved
1 Replies
154 Views
Hi, I generated code signing certificates on a computer "A" and using an apple ID "X". Can I use the certificate to sign binary using a computer "B" and with an apple ID "Y" ? Thank you for your help Currently I get the error message: codesign --force --verify --verbose --sign "Developer ID Application: XXXXX (XXXXXXX)" the_binary_to_sign --option runtime error: The specified item could not be found in the keychain.
Posted
by
Post not yet marked as solved
0 Replies
130 Views
General: DevForums tags: Code Signing, Signing Certificates, Provisioning Profiles, Entitlements Developer Account Help — This document is good in general but, in particular, the Reference section is chock-full of useful information, including the names and purposes of all certificate types issued by Apple Developer web site, tables of which capabilities are supported by which distribution models on iOS and macOS, and information on how to use managed capabilities. TN3125 Inside Code Signing: Provisioning Profiles — This includes links to other technotes in the Inside Code Signing series. Certificate Signing Requests Explained DevForums post --deep Considered Harmful DevForums post Entitlements documentation Don’t Run App Store Distribution-Signed Code DevForums post Mac code signing: DevForums tag: Developer ID Creating Distribution-Signed Code for Mac DevForums post Packaging Mac Software for Distribution DevForums post Manual Code Signing Example DevForums post Placing Content in a Bundle documentation Embedding Nonstandard Code Structures in a Bundle documentation Embedding a Command-Line Tool in a Sandboxed App documentation Signing a Daemon with a Restricted Entitlement documentation For problems with notarisation, see Notarisation Resources. For problems with the trusted execution system, including Gatekeeper, see Trusted Execution Resources. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com"
Posted
by
Post marked as solved
1 Replies
181 Views
The application I'm working needs access to a shared network drive while in development. This nominally works, but every time the app is recompiled (so hundreds of times a day), I have to give it permission to access a network volume. For obvious reasons, that isn't helpful. Does anyone know how to grant network share access permanently? Barring that, is there a way to disable that security setting, preferably with a capability/entitlement, or at the system level as a last resort? (The app does have the proper credentials granted in System Preferences, but I presume its signature or something changes with each recompile.)
Posted
by
dwn
Post not yet marked as solved
1 Replies
221 Views
I have an iOS app that isn't acceptable for the App Store (it is used to open the front door of my apartment building so not of general interest). I can install it on my iPhone from Xcode easily enough but after a week it becomes "no longer available". I assume this is because the signature expires. I created a new code signing certificate using Keychain Access that lasts much longer. I then found the archive of my app that Xcode produced, removed the signature and resigned it with my new certificate: codesign --remove-signature -v Products/Applications/FrontDoor.app codesign -s "My Self Signed Code Signing Cert" -v Products/Applications/FrontDoor.app Now I am stuck trying to work out how to load the archive onto my (and hopefully my partner's) iPhone(s). Am I on the right track or is there a better way to handle this? Is it possible to load an archive onto an iPhone connected via USB?
Posted
by
Post not yet marked as solved
0 Replies
119 Views
This post is part of a cluster of posts related to the trusted execution system. If you found your way here directly, I recommend that you start at the top. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Don’t Run App Store Distribution-Signed Code App Store distribution-signed code is intended to be uploaded to the App Store. You can’t run it locally. Except when you can! To avoid confusing yourself, don’t attempt to run App Store distribution-signed code. Intended Purpose App Store distribution-signed code is intended to be uploaded to the App Store. When you upload code to the App Store, it checks the code’s signature as part of the distribution process. App Store distribution-signed code is not intended to be run locally. That’s what development-signed code is for! If you want to test your App Store product before shipping it to users: For day-to-day work, use Development distribution. For limited testing, use Ad Hoc or Enterprise distribution (not available on macOS) or Developer ID distribution (only available on macOS). For wider testing, use TestFlight. Note Not all capabilities are supported by Developer ID distribution. For the details, see Developer Account Help > Supported capabilities (macOS). macOS Gotcha Most Apple platforms completely block you from running App Store distribution-signed code. The exception here is macOS, which runs distribution-signed code under some circumstances. Specifically, macOS runs distribution-signed code if the code claims no restricted entitlements. If the code claims a restricted entitlement that claim must be authorised by a provisioning profile. It’s not possible to create a profile that does that: A macOS App Development or Developer ID profile never authorises the certificate from your distribution signing identity. A Mac App Store profile never authorises execution on your machine. The lack of a valid profile means that the restriction entitlement is not authorised and your app will crash on launch. For more details on what that crash looks like, see Resolving Code Signing Crashes on Launch. For detailed information about provisioning profiles, see TN3125 Inside Code Signing: Provisioning Profiles. Even though there are some cases where App Store distribution-signed code will run on the Mac, the general rule is the same there as it is for other platforms: Don’t run App Store distribution-signed code. Revision History 2022-06-01 Added App Store to the title to make the subject clearer. Made similar changes throughout the text. 2022-05-31 First posted.
Posted
by
Post marked as solved
2 Replies
272 Views
I have been working on signing an app from a developer for our own purpose of publishing it to our intune company portal. The older version of the app I can sign and publish without issue. We do have an enterprise dev account, and all they provide us is the source code. The original version does not use Push notifications, nor does it show to have any framework subfolders. That one I sign by this script I've modified over time, ( security cms -D -i [mobilprovisionfilenamefromentdevsite].mobileprovision > provision.plist /usr/libexec/PlistBuddy -x -c 'Print :Entitlements' provision.plist > entitlements.plist unzip -qq [appname]22_5_1.ipa rm -rf Payload/[appname].app/_CodeSignature/ cp [mobilprovisionfilenamefromentdevsite].mobileprovision Payload/[appname].app/embedded.mobileprovision /usr/bin/codesign --force --deep --verify --sign "[Our Certificate name redacted]" -i [the app identity name from the identity creation] --entitlements entitlements.plist Payload/[appname].app/Frameworks/* codesign -dvv Payload/[appname].app/ zip -qr [appname]22_5_1-resigned.ipa Payload/ #Copy the support files for backup mkdir [appname]22_5_1-resigned-support mv entitlements.plist [appname]22_5_1-resigned-support mv Payload [appname]22_5_1-resigned-support mv provision.plist [appname]22_5_1-resigned-support ) This works fine for the old version without Frameworks or Push Notifications The New One I have just added two lines to the script to sign the FrameWorks. rm -rf Payload/[appname].app/Frameworks/*/_CodeSignature/ /usr/bin/codesign --force --deep --verify --sign "[Our Certificate name redacted]" -i [the app identity name from the identity creation] --entitlements entitlements.plist Payload/[appname].app/Frameworks/* When I try it with or without signing the FrameWorks I am unable to get the app to function. It will load on the IPhones then just give error of "Install Pending" or "Install Failed" (0x87D13B64) We do not have access to the source code, so I cannot put it into XCode to sign it. I did recreate the mobile provisioning profile with APN and created a Cert to attach to it. I'm not sure if I need to add that certificate somewhere else or if I'm signing something wrong, but this new version is kicking my ****..
Posted
by
Post not yet marked as solved
3 Replies
292 Views
I am a developer. I have distributed apps via the Apple Store Connect. Today I wrote a fun, simple Xcode app for my friend's 2-yr-old son. The app contains family photos etc so should not be made public. I have deployed the app on my iPhone but would love to have my friend, my friend's wife, as well as the grandparents and may be a couple of friends to have the app on their different iPhones. Can anyone advise as to what is the simplest way of doing this? Thank you.
Posted
by
Post not yet marked as solved
5 Replies
337 Views
Our TPP excludes our own processes from oversight, which makes some things very easy. Only I just found out that when our app uses a WKWebView... it's very securely shuffled off into its own process. With its own signing identifier. And a ppid of launchd. How could I tell that a com.apple.WebKit.Networking process is related to our process? (I note that the Endpoint Security Framework has added a "responsible" audit token, presumably for this sort of situation.)
Posted
by
Post not yet marked as solved
0 Replies
158 Views
This post is part of a cluster of posts related to the trusted execution system. If you found your way here directly, I recommend that you start at the top. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Resolving Library Loading Problems On macOS the dynamic linker is responsible for loading the dynamic libraries used by your process. There are two parts to this: When a process runs an executable, the dynamic linker loads all the libraries used by that executable, the libraries used by those libraries, and so on. A process may load libraries at runtime using APIs like dlopen and NSBundle. For information the dlopen and friends, see the dlopen man page. The dynamic linker works closely with the trusted execution system to ensure that it only loads appropriate libraries. A critical concern is dynamic library impersonation attacks. If your program references a library, you want the dynamic linker to load that copy of the library, and not some other copy installed by an attacker. The primary protection is library validation. If library validation is enabled on an executable, the trusted execution system only allows the process to load code signed by Apple or with the same Team ID as the executable. Library validation is enabled by the [Hardened Runtime][refHR] but you may opt out of it using the Disable Library Validation Entitlement (com.apple.security.cs.disable-library-validation) entitlement. IMPORTANT Leave library validation enabled. Only disable it if your app needs to load plug-ins from other third-party developers. Disabling library validation makes it harder to pass Gatekeeper. See Resolving Gatekeeper Problems Caused by Dangling Load Command Paths for the details. When the dynamic linker fails to load a library it includes an explanation in the crash report. For example: Termination Reason: Namespace DYLD, Code 1 Library missing Library not loaded: @rpath/libEtranger.dylib Referenced from: /Users/USER/*/LinkToEtranger.app/Contents/MacOS/LinkToEtranger Reason: … (terminated at launch; ignore backtrace) Application Specific Information: Library not loaded: @rpath/libEtranger.dylib Referenced from: … Reason: … This explanation is likely to be truncated by the crash reporting system. To see the full log, run the app from Terminal: % ./LinkToEtranger.app/Contents/MacOS/LinkToEtranger dyld[79650]: Library not loaded: @rpath/libEtranger.dylib Referenced from: …/LinkToEtranger.app/Contents/MacOS/LinkToEtranger Reason: tried: '…/LinkToEtranger.app/Contents/MacOS/../Frameworks/libEtr anger.dylib' (code signature in <E16EDD14-CE5A-33BC-9B06-554A3BC12C51> '…/LinkToEtranger.app/Contents/Frameworks/libEtranger.dylib' not valid for use in process: mapping process and mapped file (non-platform) have different Team IDs), '…/LinkToEtranger.app/Contents/MacOS/../ Frameworks/libEtranger.dylib' (code signature in <E16EDD14-CE5A-33BC- 9B06-554A3BC12C51> '…/LinkToEtranger.app/Contents/Frameworks/ libEtranger.dylib' not valid for use in process: mapping process and mapped file (non-platform) have different Team IDs), '/usr/local/lib/ libEtranger.dylib' (no such file), '/usr/lib/libEtranger.dylib' (no such file) zsh: abort ./LinkToEtranger.app/Contents/MacOS/LinkToEtranger The Reason line is super long, so break it up by attempt: '…/LinkToEtranger.app/Contents/MacOS/../Frameworks/libEtranger.dylib' (…), '/usr/local/lib/libEtranger.dylib' (no such file), '/usr/lib/libEtranger.dylib' (no such file) Each entry starts with a place that the dynamic linker attempted to find library and then has text inside parentheses, like no such file, explaining what went wrong. Note The exact format of these messages varies from release-to-release of macOS. Many of these reasons are unrelated to the trusted execution system. For example, no such file means that the library isn’t present on disk. There are, however, three common trusted execution issues: Library validation Use of an old macOS SDK Restricted entitlements on library code For more information about the dynamic linker, see the dyld man page. Specifically, the DYLD_PRINT_SEARCHING environment variable is super useful when debugging library loading problems. Library Validation In any real world situation the Reason output from the dynamic linker is super long. To understand it better, break it up by attempt: '…/LinkToEtranger.app/Contents/MacOS/../Frameworks/libEtranger.dylib' (code signature in <E16EDD14-CE5A-33BC-9B06-554A3BC12C51> '…/LinkToEtranger.app/Contents/Frameworks/libEtranger.dylib' not valid for use in process: mapping process and mapped file (non-platform) have different Team IDs), '/usr/local/lib/libEtranger.dylib' (no such file), '/usr/lib/libEtranger.dylib' (no such file) The dynamic linker looked in three different places: The app’s Frameworks directory /usr/local/lib /usr/lib The first one is the important one because its path matches the expected location of the library. And the dynamic linker has logged an excellent explanation of the problem: code signature in … '…/LinkToEtranger.app/Contents/Frameworks/ libEtranger.dylib' not valid for use in process: mapping process and mapped file (non-platform) have different Team IDs In summary, the dynamic linker didn’t load this copy of libEtranger.dylib because it’s not a system library (non-platform) and it has a different Team ID from the process’s main executable. A quick trip to codesign confirms this: % codesign -d -vvv LinkToEtranger.app … TeamIdentifier=SKMME9E2Y8 … % codesign -d -vvv LinkToEtranger.app/Contents/Frameworks/libEtranger.dylib … TeamIdentifier=VL9SQP756U … How you fix this depends on the nature of your product. If this library is installed as part of your product, re-sign the library with a signing identity associated with your Team ID. Do this even if you didn’t build the code yourself. After all, you were responsible for putting the library on the user’s machine, and its signature should reflect that. One other possibility is that you’re building a program that supports plug-ins and thus you need to load a plug-in that was signed by another third-party developer. In this case the fix is to disable library validation by signing your executable with the Disable Library Validation Entitlement entitlement (com.apple.security.cs.disable-library-validation). IMPORTANT Disabling library validation makes it harder to pass Gatekeeper. See Resolving Gatekeeper Problems Caused by Dangling Load Command Paths for the details. Use of an Old macOS SDK Another dynamic library load failure related to the trusted execution system looks like this: code signature in … '…/LinkToDodo.app/Contents/Frameworks/libDodo.dylib' not valid for use in process: mapped file has no cdhash, completely unsigned? Code has to be at least ad-hoc signed. Note The cdhash in this message refers to a code directory hash. For more information on cdhashes, see TN3126 Inside Code Signing: Hashes This is harder to understand, not least because the library is actually signed: % codesign -d -vvv LinkToDodo.app/Contents/Frameworks/libDodo.dylib … Authority=Apple Development: … … The explanation can be found tucked away in Notarizing macOS Software Before Distribution, which says: Apple's notary service requires you to adopt the following protections: … Link against the macOS 10.9 or later SDK macOS 10.9 introduced important code signing improvements. The hardened runtime depends on those improvements. It confirms their presence by looking at the SDK that the code was built with. If the code was built with an old SDK, or has no record of the SDK it was built with, the hardened runtime refuses to load it. In this example, the LinkToDodo app was linked to a modern SDK but the libDodo.dylib has no record of the SDK it was built with: % vtool -show-build LinkToDodo.app/Contents/MacOS/LinkToDodo … cmd LC_BUILD_VERSION … sdk 12.3 … % vtool -show-build LinkToDodo.app/Contents/Frameworks/libDodo.dylib LinkToDodo.app/Contents/Frameworks/libDodo.dylib: % That explains the error: The process has the hardened runtime enabled. The hardened runtime requires that all code be built with the macOS 10.9 SDK or later. libDodo.dylib has no record of the SDK it was build with, so the trusted execution system blocks it from loading. The dynamic linker reports that in its explanation of the problem. The best fix is to rebuild the code from source with the latest tools. If you can’t do that right now, see Notarisation and the macOS 10.9 SDK for a workaround. IMPORTANT This is a short-term compatibility measure. Plan to rebuild this code from source as soon as possible. If you got the code from another third-party developer, make sure they’re aware of this issue. Finally, if you can only reproduce this problem in the field and have managed to snag a sysdiagnose log of it, look in the system log for a log entry like this: type: default time: 2022-05-20 13:12:11.185889 +0100 process: kernel category: <Missing Description> message: …/LinkToDodo.app/Contents/Frameworks/libDodo.dylib: Possible race detected. Rejecting. That’s one cryptic smoking gun! For general information about the system log, see Your Friend the System Log. Restricted Entitlements on Library Code The third dynamic library load failure related to the trusted execution system looks like this: … OS Version: macOS 11.6.5 (20G527) … Termination Reason: DYLD, [0x5] Code Signature Application Specific Information: dyld: launch, loading dependent libraries Dyld Error Message: Library not loaded: @rpath/OverlyEntitled.framework/Versions/A/OverlyEntitled Referenced from: /Users/USER/AppWithEntitlementLibrary.app/Contents/MacOS/AppWithEntitlementLibrary Reason: no suitable image found. Did find: …/AppWithEntitlementLibrary.app/Contents/MacOS/../Frameworks/OverlyEntitled.framework/Versions/A/OverlyEntitled: code signature invalid for '…/AppWithEntitlementLibrary.app/Contents/MacOS/../Frameworks/OverlyEntitled.framework/Versions/A/OverlyEntitled' … Note This crash report is from macOS 11 because macOS 12 is smart enough to completely ignore entitlements on library code. However, the code signature is valid: % codesign -v -vvv AppWithEntitlementLibrary.app/Contents/Frameworks/OverlyEntitled.framework AppWithEntitlementLibrary.app/Contents/Frameworks/OverlyEntitled.framework: valid on disk AppWithEntitlementLibrary.app/Contents/Frameworks/OverlyEntitled.framework: satisfies its Designated Requirement It also passes both of the tests outlined in the previous section: % codesign -d -vvv AppWithEntitlementLibrary.app … TeamIdentifier=SKMME9E2Y8 … % codesign -d -vvv AppWithEntitlementLibrary.app/Contents/Frameworks/OverlyEntitled.framework … TeamIdentifier=SKMME9E2Y8 … % vtool -show-build AppWithEntitlementLibrary.app/Contents/Frameworks/OverlyEntitled.framework/Versions/A/OverlyEntitled … sdk 12.3 … The issue is that the framework is signed with a restricted entitlement: % codesign -d --entitlements - AppWithEntitlementLibrary.app/Contents/Frameworks/OverlyEntitled.framework … [Dict] [Key] com.apple.developer.networking.vpn.api [Value] [Array] [String] allow-vpn Entitlements are only effective when applied to a main executable. Code that isn’t a main executable is called library code, and that includes frameworks, dynamic libraries, and bundles. Do not apply entitlements to library code. At best it’s benign. At worse, it causes a code signing crash like this. Note For details on what constitutes a main executable, see Creating Distribution-Signed Code for Mac The Entitlements on macOS section of TN3125 Inside Code Signing: Provisioning Profiles define restricted entitlement and makes it clear that, on macOS, every restricted entitlement claimed by an executable must be authorised by its provisioning profile. However, library code does not have an embedded provisioning profile: A shared library has no bundle structure, and thus can’t include a provisioning profile. Library code with a bundle structure, frameworks and bundles, could have a provisioning profile but most tools, including Xcode, do not embed one. So, the OverlyEntitled framework is claiming a restricted entitlement but that claim isn’t authorised by a profile and thus the trusted execution system tells the dynamic linker not to load it. To fix this, change your code signing setup so that only main executables claim entitlements. For detailed advice on that topic, see Creating Distribution-Signed Code for Mac. IMPORTANT The number one cause of this problem is folks signing their code with --deep. Don’t do that, for this reason and for the other reasons outlined in --deep Considered Harmful. Revision History 2022-06-13 Added the Restricted Entitlements on Library Code section. 2022-05-20 First post.
Posted
by
Post not yet marked as solved
0 Replies
127 Views
This post is part of a cluster of posts related to the trusted execution system. If you found your way here directly, I recommend that you start at the top. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Resolving Gatekeeper Problems Gatekeeper strives to ensure that only trusted software runs on a user’s Mac. It’s important that your code pass Gatekeeper. If not, you’re likely to lose a lot of customers, and your users’ hard-won trust. There are three common Gatekeeper problems: App blocked by a dangling load command path Lack of notarisation Command-line tool blocked by Gatekeeper The first problem is by far the most common. For the details, see Resolving Gatekeeper Problems Caused by Dangling Load Command Paths. For general information about Gatekeeper, read Apple > Developer > Signing Mac Software with Developer ID and Apple > Support > Safely open apps on your Mac. IMPORTANT This post focuses on Developer ID-signed code. Gatekeeper should not block App Store apps. If an app downloaded from the App Store fails to run, it’s likely to be some other trusted execution issue. For more about this, read Resolving Trusted Execution Problems. Identifying a Notarisation Problem Gatekeeper requires that your app be notarised. If not, it will block the execution of your app with a generic, user-level message. If you find your app blocked by Gatekeeper, check if this is a notarisation issue by looking in the system log for an entry like this: type: info time: 2022-05-11 14:57:21.812176 -0700 process: syspolicyd subsystem: com.apple.syspolicy category: default message: ticket not available: 2/2/8b7410713591e6c79ea98f0132136f0faa55d22a Note If the ticket details show as <private>, enable private data in the system log. For information on how to do that, see Recording Private Data in the System Log. For general information about the system log, see Your Friend the System Log. The long hex number is the code directory hash, or cdhash, of the offending code. In this example, it’s the cdhash of the app itself: % codesign -d -vvv /Applications/NotNotarised.app … CDHash=8b7410713591e6c79ea98f0132136f0faa55d22a … However, in some cases it may be the cdhash of some library referenced by the app. For more information about cdhashes, see TN3126 Inside Code Signing: Hashes. Resolving a Notarisation Problem The obvious cause of this problem is that you haven’t notarised your app. For information on how to do that, see Notarizing macOS Software Before Distribution. If you have notarised your app and yet you still see this problem, something more subtle is happening. For example, your app might reference a dynamic library that wasn’t seen by the notary service. To investigate this: Fetch the notary log for your app. For advice on that, see Fetching the Notary Log. Confirm that the notary log matches the app you installed. Look in the notary log for the sha256 property. Its value is a SHA-256 hash of the file received by the notary service. Check that this matches the SHA-256 hash of the file you used to install your app. If not, see Hash Mismatch, below. Search the notary log for the cdhash value from the Gatekeeper log message. If the notary log doesn’t contain that cdhash, that code wasn’t included in the notarised ticket. It’s possible that you failed to submit the code to the notary service, that it was switched out with a different version after you notarised your app, that it was package in some way that the notary service couldn’t see it, or that something went wrong within the notary service. Hash Mismatch If you stapled your notarised ticket to the file used to install your app then the hashes in step 2 of the previous section won’t match. What to do depends on the file type: If the file used to install your app was a zip archive (.zip), you definitely have the wrong file. Zip archives don’t support stapling. If the file used to install your app was a signed disk image (.dmg), compare the disk image’s cdhash with the cdhash for the disk image in the notary log. If those match, you know you’re working with the same disk image. To dump a disk image’s cdhash, run the codesign tool as follows: % codesign -d -vvv DISK_IMAGE … CDHash=d963af703ac2e54af6609e9ad309abee7b66fae2 … Replace DISK_IMAGE with the path to your disk image. If the file used to install your app was a disk image but it wasn’t signed, switch to a signed disk image. It’s generally a better option. If the file used to install your app was an installer package (.pkg), there’s no good way to know if this is the correct package. In this case, modify your notarisation workflow to retain a copy of the file before it was modified by stapler. Tool Blocked by Gatekeeper If your product includes a command-line tool, you might notice this behaviour: When you double click the tool in Finder, it’s blocked by Gatekeeper. When you run the tool from within Terminal, it works. This is a known bug in macOS (r. 58097824). The issue is that, when you double click a tool in the Finder, it doesn’t run Gatekeeper’s standard execution logic. Rather, the Finder passes the tool to Terminal as a document and that opens a window (and associated shell) in which to run that document. This triggers Gatekeeper’s document logic, and that logic always blocks the tool. There are two ways around this: Embed your tool in an application. If the user runs the application first, Gatekeeper runs its normal application check. If the user allows the app to run, Gatekeeper records that decision and applies it to the app and any code within the app, including your tool. Install your tool using an installer package. When the user goes to install the package, Gatekeeper checks it. Assuming that check passes, Gatekeeper does no further checks on the content it installed.
Posted
by
Post not yet marked as solved
0 Replies
125 Views
This post is part of a cluster of posts related to the trusted execution system. If you found your way here directly, I recommend that you start at the top. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Resolving Gatekeeper Problems Caused by Dangling Load Command Paths Gatekeeper strives to ensure that only trusted software runs on a user’s Mac. It’s important that your code pass Gatekeeper. If not, you’re likely to lose a lot of customers, and your users’ hard-won trust. The most common reason for Gatekeeper to block an app is a dangling load command. To understand this issue, you first need to understand library validation. Library validation is an important security feature on macOS. If library validation is enabled on an executable, the process running that executable can only load code signed by Apple or with the same Team ID as the executable. This prevents a wide range of dynamic library impersonation attacks. Library validation is enabled by the Hardened Runtime but you may opt out of it using the Disable Library Validation Entitlement (com.apple.security.cs.disable-library-validation) entitlement. IMPORTANT Leave library validation enabled. Only disable it if your app needs to load plug-ins from other third-party developers. When Gatekeeper checks an app it looks at the state of library validation. If library validation is disabled, Gatekeeper does an extensive check of the app’s Mach-O images in an attempt to prevent dynamic library impersonation attacks. If library validation is enabled, Gatekeeper skips that check because library validation prevents such attacks. The upshot of this is that, if you disable library validation, it’s harder to pass Gatekeeper. Note The Swift Package Manager creates a dangling load command when you build a command-line tool for the Mac. For more on that issue, see the Compiler adds RPATH to executable, making macOS Gatekeeper angry thread on Swift Forums. Find Dangling Load Command Paths If your app is rejected by Gatekeeper, look in the system log for entries like this: type: error time: 2022-05-11 15:00:36.296159 -0700 process: XprotectService subsystem: com.apple.xprotect category: xprotect message: File /Applications/DanglingRPath.app/Contents/MacOS/DanglingRPath failed on rPathCmd /Users/mrgumby/Work/TrustedExecutionFailures/CoreWaffleVarnishing.framework/Versions/A/CoreWaffleVarnishing (rpath resolved to: (path not found), bundleURL: /Applications/DanglingRPath.app) In this example the entry mentions rPathCmd, and that’s a good way to search for such problems. Also search for loadCmd, which indicates a similar problem. IMPORTANT If the paths in the log entry are all <private>, enable private data in the system log. For information on how to do that, see Recording Private Data in the System Log. For general information about the system log, see Your Friend the System Log. In this example Gatekeeper has rejected the DanglingRPath app because: It references a framework, CoreWaffleVarnishing, using an rpath-relative reference. The rpath includes an entry that points outside of the app’s bundle, to a directory called /Users/mrgumby/Work. This opens the app up to a dynamic library impersonation attack. If an attacker placed a malicious copy of CoreWaffleVarnishing in /Users/mrgumby/Work, the DanglingRPath app would load it. To find the offending rpath entry, run otool against each Mach-O image in the app looking for a dangling LC_RPATH load command. For example: % otool -l DanglingRPath.app/Contents/MacOS/DanglingRPath | grep -B 1 -A 2 LC_RPATH Load command 18 cmd LC_RPATH cmdsize 48 path @executable_path/../Frameworks (offset 12) Load command 19 cmd LC_RPATH cmdsize 56 path /Users/mrgumby/Work (offset 12) This app has two LC_RPATH commands. The one, for @executable_path/../Frameworks, is fine: It points to a location within the app’s bundle. In contrast, the one for /Users/mrgumby/Work is clearly dangling. In this example, the dangling rpath entry is in the main executable but that’s not always the case; you might find it lurking in some deeply nested dynamic library. Keep in mind that this is only an issue because the app has library validation disabled: % codesign -d --entitlements - DanglingRPath.app Executable=/Users/mrgumby/Desktop/DanglingRPath.app/Contents/MacOS/DanglingRPath [Dict] [Key] com.apple.security.cs.disable-library-validation [Value] [Bool] true If library validation were enabled, Gatekeeper would skip this check entirely, and thus the app would sail past Gatekeeper. IMPORTANT In this example the app’s main executable has library validation disabled, but that’s not always the case. It’s common to see this problem in app’s that have multiple executables — the app itself and, say, one or two embedded helper tools — where one of the other executables has library validation disabled. Finally, the above example is based on rpath-relative paths. If you see a log entry containing the text loadCmd, search for dangling paths in LC_LOAD_DYLIB load commands. Fix Dangling Load Command Paths The best way to fix this problem is to not disable library validation. Library validation is an important security feature. By disabling it, you introduce this problem and reduce the security of your app. Conversely, by re-enabling it, you fix this problem and you improve security overall. The only situation where it makes sense to disable library validation is if your app loads plug-ins from other third-party developers. In that case, fixing this problem requires you to find and eliminate all dangling load command paths. There are two possibilities here: The dangling load command path is in a Mach-O image that you built from source. Or it’s in a Mach-O image that you got from a vendor, for example, a library in some third-party SDK. In the first case, solve this problem by adjusting your build system to not include the dangling load command path. In the second case, work with the vendor to eliminate the dangling load command path. If the vendor is unwilling to do this, it’s possible, as a last resort, to fix this problem by modifying the load commands yourself. For an example of how you might go about doing this, see Embedding Nonstandard Code Structures in a Bundle. And once you’re done, and your product has shipped, think carefully about whether you want to continue working with this vendor. Revision History 2022-06-13 Added a link to a related Swift Forums thread. 2022-05-20 First posted.
Posted
by
Post not yet marked as solved
0 Replies
194 Views
This post is part of a cluster of posts related to the trusted execution system. If you found your way here directly, I recommend that you start at the top. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Resolving Code Signing Crashes on Launch A code signing crash has the following exception information: Exception Type: EXC_CRASH (SIGKILL (Code Signature Invalid)) IMPORTANT Most developers never see a code signing crash because they use Xcode to build and sign their product. Xcode’s code signing infrastructure detects problems that could cause a code signing crash, and its automatic code signing fixes them for you! If you’re having problems with code signing crashes and you can use Xcode but aren’t, consider making the switch Xcode. The most common code signing crash is a crash on launch. To confirm that, look at the thread backtraces: Backtrace not available If you see valid thread backtraces this is not a crash on launch. Go back to Resolving Trusted Execution Problems and read through the Code Signing Crashes After Launch section. If you see no thread backtraces, your code didn’t run at all. The trusted execution system has blocked it. In most cases there is some evidence of the problem in the system log. For example: type: error time: 2022-05-19 06:29:17.640331 -0700 process: taskgated-helper subsystem: com.apple.ManagedClient category: ProvisioningProfiles message: com.example.apple-samplecode.OverClaim: Unsatisfied entitlements: com.apple.overclaim This indicates that the OverClaim app, with bundle ID com.example.apple-samplecode.OverClaim, claimed a restricted entitlement, com.apple.overclaim, that wasn’t authorised by a provisioning profile. For more information about provisioning profiles, see TN3125 Inside Code Signing: Provisioning Profiles. Specifically, the Entitlements on macOS section discusses the concept of restricted entitlements. For general information about the system log, see Your Friend the System Log. Normalise the Entitlements Property List Entitlement property list files look like text and so it’s tempting to edit them with a text editor. This can lead to all sorts of problems. If you have code whose entitlements property list contains comments, non-Unix line endings, or other weird formatting, the trusted execution system may block it. To avoid such problems, normalise your entitlements property list before passing it to codesign. For example: % plutil -convert xml1 MyApp.plist % codesign -s III --entitlements MyApp.plist MyApp.app Problems like this typically show up on older systems. Modern systems use DER-encoded entitlements, as discussed in The future is DER section of TN3125. A related gotcha is line breaks. Consider this entitlements property list file: % cat MyApp.plist … <plist version="1.0"> <dict> <key> com.apple.security.cs.disable-library-validation</key> <true/> </dict> </plist> This is a valid property list but it doesn’t do what you think it does. It looks like it claims the com.apple.security.cs.disable-library-validation entitlement but in reality it claims \ncom.apple.security.cs.disable-library-validation. The system treats the latter as a restricted entitlement and thus requires it to be authorised by a profile. Of course no such profile will authorise that entitlement, and so the app is blocked by the trusted execution system. Similarly, consider this: % cat MyApp.plist … <plist version="1.0"> <dict> <key> com.apple.security.cs.disable-library-validation</key> <true/> </dict> </plist> This claims com.apple.security.cs.disable-library-validation, note the leading space, and that’s also blocked by the trusted execution system. Check for Unauthorised Entitlements Sometimes the system log may not make it obvious what’s gone wrong. It may be easier to work this out by looking at the built program. The most common cause of problems like this is the app claiming a restricted entitlement that’s not authorised by a provisioning profile. To start your investigation, dump the entitlements to check for restricted entitlements: % codesign -d --entitlements - "OverClaim.app" …/OverClaim.app/Contents/MacOS/OverClaim [Dict] [Key] com.apple.application-identifier [Value] [String] SKMME9E2Y8.com.example.apple-samplecode.OverClaim [Key] com.apple.developer.team-identifier [Value] [String] SKMME9E2Y8 [Key] com.apple.overclaim [Value] [Bool] true [Key] com.apple.security.get-task-allow [Value] [Bool] true In this case all the entitlements except com.apple.security.get-task-allow are restricted. Note If there are no restricted entitlements, something else has gone wrong. Go back to Resolving Trusted Execution Problems and look for other potential causes. Now check that the provisioning profile was embedded correctly and extract its payload: % ls -l "OverClaim.app/Contents/embedded.provisionprofile" … OverClaim.app/Contents/embedded.provisionprofile % security cms -D -i "OverClaim.app/Contents/embedded.provisionprofile" -o "OverClaim-payload.plist" Check that the profile applies to this app by dumping the com.apple.application-identifier entitlement authorised by the profile: % /usr/libexec/PlistBuddy -c "print :Entitlements:com.apple.application-identifier" OverClaim-payload.plist SKMME9E2Y8.com.example.apple-samplecode.* This should match the com.apple.application-identifier entitlement claimed by the app. Repeat this for all the remaining restricted entitlements: % /usr/libexec/PlistBuddy -c "print :Entitlements:com.apple.developer.team-identifier" OverClaim-payload.plist SKMME9E2Y8 % /usr/libexec/PlistBuddy -c "print :Entitlements:com.apple.overclaim" OverClaim-payload.plist Print: Entry, ":Entitlements:com.apple.overclaim", Does Not Exist In this example the problem is the com.apple.overclaim entitlement, which is claimed by the app but not authorised by the profile. If that’s the case for your program, you have two choices: If you program doesn’t need this entitlement, update your code signing to not claim it. If you program relies on this entitlement, update your profile to authorise it. The entitlement allowlist in the profile is built by the Apple Developer website based on the capabilities enabled on your App ID. To change this allowlist, modify your App ID capabilities and rebuild your profile. Some capabilities are only available on some platforms and, within that platform, for some distribution channels. For these details for macOS, see Developer Account Help > Reference > Supported capabilities (macOS). Some capabilities require review and approval by Apple. For more on this, see Developer Account Help > Reference > Provisioning with managed capabilities. Check the Signing Certificate If your program’s entitlements look good, the next most likely problem is that your program was signed by a signing identity whose certificate is not authorised by the profile. To debug this, first extract the certificate chain from your program: % codesign -d --extract-certificates=signed-with- "OverClaim.app" … % for i in signed-with-* ; do mv "${i}" "${i}.cer" ; done The first certificate is the one that matters: % certtool d "signed-with-0.cer" Serial Number : 53 DB 60 CC 85 32 83 DE 72 D9 6A C9 8F 84 78 25 … Subject Name : Other name : UT376R4K29 Common Name : Apple Development: Quinn Quinn (7XFU7D52S4) OrgUnit : SKMME9E2Y8 Org : Quinn Quinn Country : US … Now check this against each of the certificates authorised by the profile. Start by extracting the first one: % plutil -extract DeveloperCertificates.0 raw -o - OverClaim-payload.plist | base64 -D > "authorised0.cer" % certtool d "authorised0.cer" Serial Number : 46 A8 EF 2C 52 54 DE FD D1 76 9D 3A 41 7C 9E 43 … Subject Name : Other name : UT376R4K29 Common Name : Mac Developer: Quinn Quinn (7XFU7D52S4) OrgUnit : SKMME9E2Y8 Org : Quinn Quinn Country : US … That’s not a match. So try the next one: % plutil -extract DeveloperCertificates.1 raw -o - OverClaim-payload.plist | base64 -D > authorised1.cer % certtool d "authorised1.cer" Serial Number : 53 DB 60 CC 85 32 83 DE 72 D9 6A C9 8F 84 78 25 … Subject Name : Other name : UT376R4K29 Common Name : Apple Development: Quinn Quinn (7XFU7D52S4) OrgUnit : SKMME9E2Y8 Org : Quinn Quinn Country : US … This matches, which means the profile applies to this code. IMPORTANT When checking for a match, look at the Serial Number field. Don’t just rely on the Common Name field. A common mistake is to have two signing identities whose certificates have identical common names but the profile only lists one of them. If you get to the end of the list of certificate list in the profile and don’t find the certificate that the program was signed with, you know what the problem is: Your program is signed with a signing identity whose certificate is not listed in its profile. To fix this, either: Reconfigure your code signing to use a signing identity whose certificate is listed. Or update the profile to include the certificate of the signing identity you’re using. Check for Expiration If your certificates aren’t the problem, check that nothing has expired. Start with the certificate from the app’s signature: % certtool d "signed-with-0.cer" Serial Number : 53 DB 60 CC 85 32 83 DE 72 D9 6A C9 8F 84 78 25 … Not Before : 10:52:56 Apr 21, 2022 Not After : 10:52:55 Apr 21, 2023 … Also check the expiry date on the profile: % plutil -extract ExpirationDate raw -o - OverClaim-payload.plist 2023-04-21T11:02:58Z If either has expired, update it and re-sign your product. IMPORTANT Developer ID-signed code and installers include a secure timestamp. When the system checks the expiry date on a Developer ID certificate, it only checks that the certificate was valid at the time that the code was signed, base on that secure timestamp. Thus, an old Developer ID-signed app will continue to run after it’s certificate has expired. Check the Supported Devices If everything else checks out, the last thing to check is that the profile authorises the code to run on this machine. There are two cases here: Developer ID profiles authorise the code on all machines. Other profiles authorise the code on a specific list of machines. If you think you have a Developer ID profile, confirm that by looking for the ProvisionsAllDevices property: % plutil -extract "ProvisionsAllDevices" xml1 -o - "OverClaim-payload.plist" … No value at that key path or invalid key path: ProvisionsAllDevices If that’s not the case, get the ProvisionedDevices property and verify that the current machine’s provisioning UDID is listed there: % plutil -extract "ProvisionedDevices" xml1 -o - "OverClaim-payload.plist" … <array> … <string>A545CA26-80D7-5B38-A98C-530A798BE342</string> … </array> </plist> % system_profiler SPHardwareDataType … Provisioning UDID: A545CA26-80D7-5B38-A98C-530A798BE342 … If you get to the end any everything looks OK, your provisioning profile is not the cause of this crash. Return to Resolving Trusted Execution Problems for more suggestions. Revision History 2022-06-08 Added the Normalise the Entitlements Property List section. 2022-05-20 First posted.
Posted
by
Post not yet marked as solved
0 Replies
145 Views
This post is part of a cluster of posts related to the trusted execution system. If you found your way here directly, I recommend that you start at the top. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Resolving App Sandbox Inheritance Problems If you’re creating a product with the App Sandbox enabled and it crashes with a trap within _libsecinit_appsandbox, it’s likely that you’re tripping over one of the following problems: Nonheritable entitlements Changing sandbox Nothing to inherit Nonheritable Entitlements The most common cause of this problem is also the most obscure. If you have a sandboxed app with an embedded program that you run as a child process, a crash in _libsecinit_appsandbox is most likely caused by the embedded program being signed with entitlements that can’t be inherited. Imagine an, SandboxInit, with an embedded helper tool, NotHeritable. When the app runs the helper tool as a child process, the helper tool crashes with a crash report like this: Exception Type: EXC_BAD_INSTRUCTION (SIGILL) … Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 libsystem_secinit.dylib … _libsecinit_appsandbox.cold.7 + 49 1 libsystem_secinit.dylib … _libsecinit_appsandbox + 2096 2 libsystem_trace.dylib … _os_activity_initiate_impl + 51 3 libsystem_secinit.dylib … _libsecinit_initializer + 67 4 libSystem.B.dylib … libSystem_initializer + 286 5 dyld … invocation function for block in dyld4::Loade… 6 dyld … invocation function for block in dyld3::MachO… 7 dyld … invocation function for block in dyld3::MachO… 8 dyld … dyld3::MachOFile::forEachLoadCommand(Diagnost… 9 dyld … dyld3::MachOFile::forEachSection(void (dyld3:… 10 dyld … dyld3::MachOAnalyzer::forEachInitializer(Diag… 11 dyld … dyld4::Loader::findAndRunAllInitializers(dyld… 12 dyld … dyld4::APIs::runAllInitializersForMain() + 38 13 dyld … dyld4::prepare(dyld4::APIs&, dyld3::MachOAnal… 14 dyld … start + 388 The helper tool has trapped within _libsecinit_appsandbox. Look at the entitlements of the helper tool: % codesign -d --entitlements - SandboxInit.app/Contents/MacOS/NotHeritable … [Dict] [Key] com.apple.security.app-sandbox [Value] [Bool] true [Key] com.apple.security.inherit [Value] [Bool] true [Key] com.apple.security.get-task-allow [Value] [Bool] true The com.apple.security.app-sandbox and com.apple.security.inherit entitlements are fine: They configure the program to inherit its sandbox from its parent. The problem is the com.apple.security.get-task-allow entitlement, which is not compatible with this sandbox inheritance. The com.apple.security.get-task-allow entitlement is often automatically injected by Xcode. For information on how to prevent this, see Embedding a Command-Line Tool in a Sandboxed App. Some entitlements are compatible with sandbox inheritance. Unfortunately that list of entitlements is not documented (r. 93582428). The most commonly use ones are the hardened runtime exception entitlements documented in Hardened Runtime. The other entitlements on the list are pretty obscure. Changing Sandbox Another cause of a trap within _libsecinit_appsandbox is the child process trying to set up its own sandbox. If a sandboxed process runs another program as a child process, that child process always inherits its sandbox from the parent. If the program’s executable is signed with com.apple.security.app-sandbox but not com.apple.security.inherit — that is, it tries to set up a new sandbox — it will crash in _libsecinit_appsandbox. A process is not allowed to change its sandbox. To check for this problem, look for the following in the crash report: Application Specific Signatures: SYSCALL_SET_PROFILE This indicates that the process tried to setup its sandbox profile but that failed, in this case because it already has a sandbox profile. To fix this problem, either: In the child, add the com.apple.security.inherit entitlement so that it inherits its sandbox from the parent. In the parent, run the program so that it’s not a child process. For example, you could launch it using NSWorkspace. Nothing to Inherit Another cause of a trap within _libsecinit_appsandbox is when a nonsandboxed process runs another program as a child process and that other program’s executable has the com.apple.security.app-sandbox and com.apple.security.inherit entitlements. That is, the child process wants to inherit its sandbox from its parent but there’s nothing to inherit. To check for this problem, look for the following in the crash report: Application Specific Information: Process is not in an inherited sandbox. There are three ways you might fix this problem: Sandbox the parent. Unsandbox the child. Run the child in its own sandbox by removing the com.apple.security.inherit entitlement.
Posted
by
Post not yet marked as solved
0 Replies
283 Views
I help a lot of developers with trusted execution problems. For example, they might have an app being blocked by Gatekeeper, or an app that crashes on launch with a code signing error. If you encounter a problem that’s not explained here, start a new thread with the details. Make sure to add relevant tags — like Gatekeeper, Code Signing, and Notarization — so that I see your post. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Resolving Trusted Execution Problems macOS supports three software distribution channels: The user downloads an app from the App Store. The user gets a Developer ID-signed program directly from its developer. The user builds programs locally using Apple or third-party developer tools. The trusted execution system aims to protect users from malicious code. It’s comprised of a number of different subsystems. For example, Gatekeeper strives to ensure that only trusted software runs on a user’s Mac, while XProtect is the platform’s built-in antivirus technology. Note To learn more about these technologies, see Apple Platform Security. If you’re developing software for macOS your goal is to avoid trusted execution entanglements. You want users to install and use your product without taking any special steps. If, for example, you ship an app that’s blocked by Gatekeeper, you’re likely to lose a lot of customers, and your users’ hard-won trust. Trusted execution problems are rare with Mac App Store apps because the Mac App Store validation process tends to catch things early. This post is primarily focused on Developer ID-signed programs. Developers who use Xcode encounter fewer trusted execution problems because Xcode takes care of many code signing and packaging chores. If you’re not using Xcode, consider making the switch. If you can’t, consult the following for information on how to structure, sign, and package your code: Placing Content in a Bundle Embedding Nonstandard Code Structures in a Bundle Embedding a Command-Line Tool in a Sandboxed App Creating Distribution-Signed Code for Mac DevForums post Packaging Mac Software for Distribution DevForums post Gatekeeper Basics User-level apps on macOS implement a quarantine system for new downloads. For example, if Safari downloads a zip archive, it quarantines that archive. This involves setting the com.apple.quarantine extended attribute on the file. Note The com.apple.quarantine extended attribute is not documented as API. If you need to add, check, or remove quarantine from a file programmatically, use the quarantinePropertiesKey API. User-level unarchiving tools preserve quarantine. To continue the above example, if you double click the quarantined zip archive in the Finder, Archive Utility will unpack the archive and quarantine the resulting files. If you launch a quarantined app, the system invokes Gatekeeper. Gatekeeper checks the app for problems. If it finds no problems, it asks the user to confirm the launch, just to be sure. If it finds a problem, it displays an alert to the user and prevents them from launching it. The exact wording of this alert varies depending on the specific problem, and from release to release of macOS, but it generally looks like the ones shown in Apple > Support > Safely open apps on your Mac. The system may run Gatekeeper at other times as well. The exact circumstances under which it runs Gatekeeper is not documented and changes over time. However, running a quarantined app always invokes Gatekeeper. Unix-y networking tools, like curl and scp, don’t quarantine the files they download. Unix-y unarchiving tools, like tar and unzip, don’t propagate quarantine to the unarchived files. Confirm the Problem Trusted execution problems can be tricky to reproduce: You may encounter false negatives, that is, you have a trusted execution problem but you don’t see it during development. You may also encounter false positives, that is, things fail on one specific Mac but otherwise work. To avoid chasing your own tail, test your product on a fresh Mac, one that’s never seen your product before. The best way to do this is using a VM, restoring to a snapshot between runs. For a concrete example of this, see Testing a Notarised Product. The most common cause of problems is a Gatekeeper alert saying that it’s blocked your product from running. However, that’s not the only possibility. Before going further, confirm that Gatekeeper is the problem by running your product without quarantine. That is, repeat the steps in Testing a Notarised Product except, in step 2, download your product in a way that doesn’t set quarantine. Then try launching your app. If that launch fails then Gatekeeper is not the problem, or it’s not the only problem! Note The easiest way to download your app to your test environment without setting quarantine is scp. Alternatively, use xattr to remove the com.apple.quarantine extended attribute from the download before you unpack it. For more information about the xattr tool, see the xattr man page. Trusted execution problems come in all shapes and sizes. The remaining sections address the most common ones. App Blocked by Gatekeeper If your product is an app and it works correctly when not quarantined but is blocked by Gatekeeper when it is, you have a Gatekeeper problem. For advice on how to investigate such issues, see Resolving Gatekeeper Problems. App Can’t Be Opened Not all failures to launch are Gatekeeper errors. In some cases the app is just broken. For example: The app’s executable might be missing the x bit set in its file permissions. The app’s executable might be subtly incompatible with the current system. The classic example of this is trying to run a third-party app that contains arm64e code. macOS requires that third-party kernel extensions use the arm64e architecture. In other circumstances, stick to arm64 for your shipping products. If you want to test arm64e code locally, see Preparing Your App to Work with Pointer Authentication. The app’s executable might claim restricted entitlements that aren’t authorised by a provisioning profile. Or the app might have some other code signing problem. Note For more information about provisioning profiles, see TN3125 Inside Code Signing: Provisioning Profiles. In such cases the system displays an alert saying: The application “NoExec” can’t be opened. [[OK]] Note In macOS 11 this alert was: You do not have permission to open the application “NoExec”. Contact your computer or network administrator for assistance. [[OK]] which was much more confusing. A good diagnostic here is to run the app’s executable from Terminal. For example, an app with a missing x bit will fail to run like so: % NoExec.app/Contents/MacOS/NoExec zsh: permission denied: NoExec.app/Contents/MacOS/NoExec And an app with unauthorised entitlements will be killed by the trusted execution system: % OverClaim.app/Contents/MacOS/OverClaim zsh: killed OverClaim.app/Contents/MacOS/OverClaim In some cases running the executable from Terminal will reveal useful diagnostics. For example, if the app references a library that’s not available, the dynamic linker will print a helpful diagnostic: % MissingLibrary.app/Contents/MacOS/MissingLibrary dyld[88394]: Library not loaded: @rpath/CoreWaffleVarnishing.framework/Versions/A/CoreWaffleVarnishing … zsh: abort MissingLibrary.app/Contents/MacOS/MissingLibrary Code Signing Crashes on Launch A code signing crash has the following exception information: Exception Type: EXC_CRASH (SIGKILL (Code Signature Invalid)) The most common such crash is a crash on launch. To confirm that, look at the thread backtraces: Backtrace not available For steps to debug this, see Resolving Code Signing Crashes on Launch. One common cause of this problem is running distribution-signed code. Don’t do that! For details on why that’s a bad idea, see Don’t Run App Store Distribution-Signed Code. Code Signing Crashes After Launch If your program crashes due to a code signing problem after launch, you might have encountered the issue discussed in Updating Mac Software. Non-Code Signing Failures After Launch The hardened runtime enables a number of security checks within a process. Some coding techniques are incompatible with the hardened runtime. If you suspect that your code is incompatible with the hardened runtime, see Resolving Hardened Runtime Incompatibilities. App Sandbox Inheritance If you’re creating a product with the App Sandbox enabled and it crashes with a trap within _libsecinit_appsandbox, it’s likely that you’re having App Sandbox inheritance problems. For the details, see Resolving App Sandbox Inheritance Problems. Library Loading Problem Most library loading problems have an obvious cause. For example, the library might not be where you expect it, or it might be built with the the wrong platform or architecture. However, some library loading problems are caused by the trusted execution system. For the details, see Resolving Library Loading Problems. Explore the System Log If none of the above resolves your issue, look in the system log for clues as to what’s gone wrong. Some good keywords to search for include: gk, for Gatekeeper xprotect syspolicy, per the syspolicyd man page cmd, for Mach-O load command oddities amfi, for Apple mobile file integrity, per the amfid man page taskgated, see its taskgated man page yara, discussed in Apple Platform Security ProvisioningProfiles For general information the system log, see Your Friend the System Log. Revision History 2022-06-09 Added the Non-Code Signing Failures After Launch section. 2022-06-03 Added a link to Don’t Run App Store Distribution-Signed Code. Fixed the link to TN3125. 2022-05-20 First posted.
Posted
by